buglwIP - A Lightweight TCP/IP stack - Bugs: bug #43779, select(), close(), and TCP...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #43779: select(), close(), and TCP retransmission error

Submitter:  Jonathan Portwood <jpbears1>
Submitted:  Mon 08 Dec 2014 02:33:17 PM UTC
   
 
Category:  sockets/netconn Severity:  3 - Normal
Item Group:  Faulty Behaviour Status:  Fixed
Privacy:  Public Assigned to:  goldsimon
Open/Closed:  Closed Planned Release:  None
lwIP version:  1.4.1

Wed 18 Feb 2015 07:41:30 PM UTC, comment #1: 

Fixed, thanks for the report. I've changed your 'workaround' to calling 'event_callback(RCVPLUS)' but only if 'err == ERR_CLSD'.

Simon Goldschmidt <goldsimon>
Group administrator
Mon 08 Dec 2014 02:33:17 PM UTC, original submission:  

We ran across a fairly esoteric issue with the LwIP socket implementation.

The issue stems from using a TCP socket as a server. If the client sends data to the server and is done, the client sends a "FIN" with the last packet. As with all network stacks, in LwIP this results in select() notifying the application of data on the socket and then a EOF on the server side draining the socket. This is the correct behavior. In this situation you see this in the debug:

State: ESTABLISHED
tcp_receive: pcb->rttest 0 rtseq 6537 ackno 6538
tcp_receive: received FIN.
State: CLOSE_WAIT


However,  in a very specifically crafted case where the packet right before the FIN came from the client was dropped, a TCP retransmission must occur.  The FIN packet was received and queued. Then the retransmitted packet is received, and the FIN is dequeued. You see this in the debug log:

State: ESTABLISHED
tcp_receive: pcb->rttest 0 rtseq 657 ackno 6538
tcp_receive: dequeued FIN.
State: CLOSE_WAIT

In this situation, the socket layer will notify select() and the server app will read the socket.  In this situation, the last bytes of the transfer are delivered to the application, but not the EOF.  The server side never receives a direct notification of the EOF.
In the sockets.c file its this function: lwip_recvfrom().  A FIN results in a NULL msg sent to the netconn.
This results in this call returning ERR_CLSD:

 if (netconn_type(sock->conn) == NETCONN_TCP) {
        err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);

You see this in the log:
lwip_recvfrom: netconn_recv err=-12, netbuf=0

However, then below:
      if (err != ERR_OK) {
        if (off > 0) {
            ...

If off is greater than 0 then the leftover data is sent to the application and returned. The knowledge of the error (in this case CLOSED) is lost, and select() is never rewoken on the socket.  The workaround I have come up with is if this happens, grab a lock and increment the rcvevent for the socket so that select() will wake up the thread one more time and the application will recall lwip_recvfrom() and this time it will grab the EOF:

      if (err != ERR_OK) {
        if (off > 0) {
          /* update receive window */
          netconn_recved(sock->conn, (u32_t)off);
          /* already received data, return that */
          sock_set_errno(sock, 0);
          // workaround begin
          SYS_ARCH_PROTECT(lev);
          sock->rcvevent++; /* signal one more receive event for NULL */
          SYS_ARCH_UNPROTECT(lev);
          // workaround end
          return off;
        }

Again, this has to be a specific dropped packet - we ran across this because of a MAC layer issue causing that particular packet to be dropped.  It appears that if any other packet in the transmission is dropped (including the last packet) than there are no issues.

Jonathan Portwood <jpbears1>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by goldsimon (Posted a comment)
  • -email is unavailable- added by jpbears1 (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2015-02-18 goldsimon StatusNone Fixed
        Assigned toNone goldsimon
        Open/ClosedOpen Closed

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code