Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Jun 2007 18:08:13 -0700
From:      Julian Elischer <julian@elischer.org>
To:        FreeBSD Net <freebsd-net@freebsd.org>
Subject:   [6.x] problem with AIO, non-blocking sockets on freebSD and IE7 on windows.
Message-ID:  <467C727D.4060703@elischer.org>

next in thread | raw e-mail | index | archive | help

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;
                        while (so->so_state & SS_ISCONNECTED) {
                                error = tsleep(&so->so_timeo,
                                    PSOCK | PCATCH, "soclos", so->so_linger * hz);
                                if (error)
                                        break;
                        }
                }
        }

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:

========================================== 
The first + last packet output is below:
========================================== 
Source         Destination    Info
172.20.51.115  172.20.3.43    2597 > http [SYN] Seq=0 Len=0 
172.20.3.43    172.20.51.115  http > 2597 [SYN, ACK] Seq=0 Ack=1 Len=0 
172.20.51.115  172.20.3.43    2597 > http [ACK] Seq=1 Ack=1 Len=0
172.20.51.115  172.20.3.43    POST http://creative.gettyimages.com/source/<truncated>;
HTTP/1.1
172.20.51.115  172.20.3.43    HTTP
172.20.3.43    172.20.51.115  http > 2597 [ACK] Seq=1 Ack=1261 Len=0

---------------

172.20.3.43    172.20.51.115  http > 2597 [ACK] Seq=1 Ack=13729 Len=0
172.20.51.115  172.20.3.43    HTTP
172.20.3.43    172.20.51.115  HTTP/1.0 407 Proxy Authentication Required
(text/html)
172.20.3.43    172.20.51.115  HTTP
172.20.3.43    172.20.51.115  http > 2597 [FIN, ACK] Seq=1858 Ack=13729 Len=0
172.20.51.115  172.20.3.43    2597 > http [ACK] Seq=13731 Ack=1859 Len=0
172.20.3.43    172.20.51.115  http > 2597 [RST] Seq=1 Len=0
172.20.3.43    172.20.51.115  http > 2597 [RST] Seq=1859 Len=0


The ACK that comes from the client is wquite legal and in fact a FIN should follow.
however we react to it by sending a reset.

This makes IE7 throw a "generic IE error page". Even though it has all the information it 
needs.
Less that a good result for the user.

The answer is to NOT destroy the socket immediately, but to schedule it for self destruction
in FIN_WAIT_1_TIME seconds (or so_linger secs) or when the FIN turns up, whichever occurs first.

however so_close is in the wrong layer to decide to do this I think... socket code in general
has no timer related stuff.. TCPhas timers, so I thin it would require a new call into TCP
to tell it to put the session in question onto a (new) timer..

thoughts anyone?

Julian









Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?467C727D.4060703>