lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] [bug #28062] Data received directly after accepting does no


From: Simon Goldschmidt
Subject: [lwip-devel] [bug #28062] Data received directly after accepting does not wake up select
Date: Fri, 20 Nov 2009 15:32:26 +0000
User-agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; de; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5

URL:
  <http://savannah.nongnu.org/bugs/?28062>

                 Summary: Data received directly after accepting does not
wake up select
                 Project: lwIP - A Lightweight TCP/IP stack
            Submitted by: goldsimon
            Submitted on: Fr 20 Nov 2009 15:32:25 GMT
                Category: sockets
                Severity: 3 - Normal
              Item Group: Faulty Behaviour
                  Status: None
                 Privacy: Public
             Assigned to: goldsimon
             Open/Closed: Open
         Discussion Lock: Any
         Planned Release: 1.3.2
            lwIP version: CVS Head

    _______________________________________________________

Details:

As reported by Albert Bartel on lwip-devel:

Finally we found the bug that was responsible for the communication hang for
60sec after a single ack.

It could be easy reproduced with fast and short requests, much more often
with vista than with xp (because tcp/ip with vista is faster than with xp).

 

The request was received, correctly processed and a NETCONN_EVT_RCVPLUS
should be sent by calling API_EVENT() but because of speed problems the
conn->socket (that is prior also stored in the local variable s) is invalid
after the first try.

After the sys_sem_wait(socksem) it is checked again. If it is still invalid,
there is a return.

But if we now got a valid conn->socket we get the socket with sock =
get_socket(s), but s is still invalid.

 

Because s is used later, s should be set to conn->socket after we get a valid
conn->socket. (see comment)

 

        s = conn->socket;

(1)     if (s < 0) {

          /* Data comes in right away after an accept, even though

           * the server task might not have created a new socket yet.

           * Just count down (or up) if that's the case and we

           * will use the data later. Note that only receive events

           * can happen before the new socket is set up. */

          sys_sem_wait(socksem);

(2)       if (conn->socket < 0) {

            if (evt == NETCONN_EVT_RCVPLUS) {

              conn->socket--;

            }

            sys_sem_signal(socksem);

            return;

          }

          // set s to conn->socket because now conn->socket s valid

          // and s (old conn->socket) is invalid

(3)       s = conn->socket;

          sys_sem_signal(socksem);

        }

   

        sock = get_socket(s);

        if (!sock) {

          return;

        }

 

In our case it was frequently that the first check (1) failed because s
(conn->socket) was -1.

So we get into the first if (1). There we wait for the semaphore to be
signalled and after that there is a second check (2). If this check fails, we
get into the next if (2) and there we return in every case.

Otherwise, if the second check (2) succeeds, we signal the semaphore and call
sock = get_socket(s), but s is still -1. So get_socket(s) fails, we return and
the socket is not signalled, that there was data received.

 

If we get into the second if (2), the conn->socket is still invalid and the
return is correct, of course. But if we don’t get into the second if (2),
the conn->socket is valid, isn’t it?

And because s is used later on, we have got to set s to the now valid
conn->socket.

 

In our case, when we got into (1) but not into (2) we never receive a signal
that data was received, so lwip_selscan in lwip_select never returns > 0
because ->rcvevent is not incremented. And because the received data was the
HTTTP GET, no more data follows, the data is not processed and we get no
answer until the connection is closed manually (then the FIN,ACK increments
the ->rcvevent and we get the data after the connection closed).

 

So in our case it works, every connection is processed correctly. That’s
why I think, that (3) is correct and should be inserted.






    _______________________________________________________

Reply to this item at:

  <http://savannah.nongnu.org/bugs/?28062>

_______________________________________________
  Nachricht geschickt von/durch Savannah
  http://savannah.nongnu.org/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]