From nobody@FreeBSD.org  Sat Jan 26 10:55:04 2002
Return-Path: <nobody@FreeBSD.org>
Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21])
	by hub.freebsd.org (Postfix) with ESMTP id C298437B400
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 26 Jan 2002 10:55:03 -0800 (PST)
Received: (from nobody@localhost)
	by freefall.freebsd.org (8.11.6/8.11.6) id g0QIt3K19871;
	Sat, 26 Jan 2002 10:55:03 -0800 (PST)
	(envelope-from nobody)
Message-Id: <200201261855.g0QIt3K19871@freefall.freebsd.org>
Date: Sat, 26 Jan 2002 10:55:03 -0800 (PST)
From: Boyan Gadjev <bgadjev@verio.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: accept() fails after ECONNABORTED
X-Send-Pr-Version: www-1.0

>Number:         34307
>Category:       misc
>Synopsis:       accept() fails after ECONNABORTED
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    ceri
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jan 26 11:00:01 PST 2002
>Closed-Date:    Sun Jun 08 11:02:36 PDT 2003
>Last-Modified:  Sun Jun 08 11:02:36 PDT 2003
>Originator:     Boyan Gadjev
>Release:        4.5-RC
>Organization:
NTT/Verio
>Environment:
FreeBSD mail01a.rapidsite.net 4.5-RC FreeBSD 4.5-RC #0: Tue Jan 22 17:20:15 EST 2002     root@freebsd.boca.verio.net:/usr/src/sys/compile/VERIO  i386

>Description:
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
sockopt = 1; sockoptlen = 4;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sockoptlen);
sockopt = 1; sockoptlen = 4;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&sockopt, sockoptlen);
bind() ;
listen(s,200) /* i  have kern.ipc.somaxconn = 256 */

while(1) {
  confd = accept (s, (struct sockaddr *) &server, &sockaddr_len);
  if (confd < 0) {
    myerrno = errno;
    if ((myerrno != EWOULDBLOCK) && (myerrno != EAGAIN)) break;
    else {
      continue;
    }
 .............
.................
 }
}


And here is the problem. If I ignore ECONNABORTED like I do for EAGAIN
and EWOULDBLOCK then every accept() after that would NOT change 'server'
meaning that I am not able to get the remote address. I have to
actually close and recreate the socket before I use accept() again.

I tried non-blocking and blocking socket and the result is the same.
Load on the box gets betw4een 4-7 and I have thousands connections per second
to that port.


>How-To-Repeat:
 Create a small program that listens on a port and hit the port with many connections
(connect write close) till you get ECONNABORTED on the server side.

>Fix:
the only one i thought of was to recreate the socket after ECONNABORTED.
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: iedowse 
State-Changed-When: Mon Oct 14 16:18:33 PDT 2002 
State-Changed-Why:  

Hi, in the code fragment you posted, you have not shown `sockaddr_len' 
being reset to sizeof(server) each time before you call accept(). 
Could this be the cause of the behaviour you saw? From accept(2): 

The addrlen is a value-result parameter; it should initially 
contain the amount of space pointed to by addr; on return 
it will contain the actual length (in bytes) of the address 
returned. 

It looks as if accept() may reset this value-result parameter to 
zero on errors. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=34307 
State-Changed-From-To: feedback->closed 
State-Changed-By: ceri 
State-Changed-When: Sun Jun 8 11:02:35 PDT 2003 
State-Changed-Why:  
Feedback timeout (6 months or more). 
I will handle any feedback that this closure generates. 


Responsible-Changed-From-To: freebsd-bugs->ceri 
Responsible-Changed-By: ceri 
Responsible-Changed-When: Sun Jun 8 11:02:35 PDT 2003 
Responsible-Changed-Why:  
Feedback timeout (6 months or more). 
I will handle any feedback that this closure generates. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=34307 
>Unformatted:
