From owner-freebsd-net@FreeBSD.ORG Sat Jun 23 01:08:16 2007 Return-Path: X-Original-To: freebsd-net@freebsd.org Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 5742216A46C for ; Sat, 23 Jun 2007 01:08:16 +0000 (UTC) (envelope-from julian@elischer.org) Received: from outT.internet-mail-service.net (outT.internet-mail-service.net [216.240.47.243]) by mx1.freebsd.org (Postfix) with ESMTP id 47CEA13C45A for ; Sat, 23 Jun 2007 01:08:16 +0000 (UTC) (envelope-from julian@elischer.org) Received: from mx0.idiom.com (HELO idiom.com) (216.240.32.160) by out.internet-mail-service.net (qpsmtpd/0.32) with ESMTP; Fri, 22 Jun 2007 18:08:15 -0700 Received: from julian-mac.elischer.org (nat.ironport.com [63.251.108.100]) by idiom.com (Postfix) with ESMTP id 8013D125B2F for ; Fri, 22 Jun 2007 18:08:15 -0700 (PDT) Message-ID: <467C727D.4060703@elischer.org> Date: Fri, 22 Jun 2007 18:08:13 -0700 From: Julian Elischer User-Agent: Thunderbird 2.0.0.4 (Macintosh/20070604) MIME-Version: 1.0 To: FreeBSD Net Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: [6.x] problem with AIO, non-blocking sockets on freebSD and IE7 on windows. X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Jun 2007 01:08:16 -0000 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/ 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