[6.x] problem with AIO, non-blocking sockets on freebSD and IE7 on windows.

John-Mark Gurney gurney_j at resnet.uoregon.edu
Mon Jun 25 17:46:45 UTC 2007

Julian Elischer wrote this message on Mon, Jun 25, 2007 at 10:17 -0700:
> Bruce Evans wrote:
> >On Fri, 22 Jun 2007, Julian Elischer wrote:
> >
> >>If one has an event-driven process that accepts tcp connections, one 
> >>needs to set eh non-blocking socket option and use kqueue or similar 
> >>to schedule work.
> >>
> >>This is ok for data transfers, however when it comes to the close() 
> >>call there is a problem.  The problem in in the following code in 
> >>so_close()
> >>
> >>
> >>              if (so->so_options & SO_LINGER) {
> >>                      if ((so->so_state & SS_ISDISCONNECTING) &&
> >>                          (so->so_state & SS_NBIO))
> >>                              goto drop;
> >>...
> >>drop:
> >> [ continues on to destroy socket ]
> >>
> >>
> >>because SS_NBIO is set, the socket acts as if SO_LINGER was set, with 
> >>a timeout of 0.
> >>the result of this, is the following behaviour:
> >
> >[ patckets in flight get lost ]
> >
> >This seems to be the correct behaviour.  The application doesn't care
> >about its data and/or wants to close the descriptor without blocking,
> >so it doesn't turn off the blocking flag and/or wait for i/o to complete
> >(so that it can see if the i/o actually worked) before calling close().
> It's not the correct behaviour if the only packet coming back is an Ack of
> the FIN (and a FIN) because in the real world, making IE7 throw an error 
> screen is not an acceptable option. This is the sort of thing
> that gets FreeBSD thrown out on favour of "anything else".
> Believe me, our customers are "NOT HAPPY" about this.
> Instead of getting an "authorization required" page along with
> the opportunity to log in, they get an error, and no opportunity
> to log in, which makes the system unusable.
> Yes, Blame Microsoft, but we are breaking the TCP spec, not them.
> We need to fix this some how.

As bde mention, the bug is in the application...  Even SUSv2 says:
When all file descriptors associated with a pipe or FIFO special file are closed, any data remaining in the pipe or FIFO will be discarded.

Our own close(2) says:
on the last
     close of a socket(2) associated naming information and queued data are

So, failure of the application to ensure that all data is sent is the
application's fault...  bde alluded to a simple work around of clearing
the non-blocking flag which will return close to the "expected" (but
apprently broken) behavior of keeping the tcp socket around till all
remaining data has been sent...

I must note that the code you quoted has been in FreeBSD since 2.0.

> >I implemented this behaviour for tty drivers in FreeBSD.  Old BSD tty
> >drivers didn't check the nonblocking flag and didn't have a timeout,
> >so close() on tty devices tended to hang forever (normally at long
> >weekends) even for closes that should have been nonblocking.

  John-Mark Gurney				Voice: +1 415 225 5579

     "All that I will do, has been done, All that I have, has not."

More information about the freebsd-net mailing list