tech-net archive

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

Re: TCP connections clogging up accf_http(9) (was: ESTABLISHED sockets with no fd open? (was: generating ECONNRESET with no syscall?))



> The attached patch (untested, not even compiled!) may work.  I believe it
> is strictly fair: the longer a cxn sits idle, sending no valid request,
> the more likely it is to be passed through to the application, which may
> in turn drop it.
Thanks for this, it essentially works.  However while it does remove one
pending socket from q0 by calling soisconnected, it still runs into the
return NULL at the bottom, so that particular attempt to establish a TCP
connection still fails.  The next one works then, though.

Since soisconnected makes room on q0, I figure it might as well proceed
allocating the new socket if soisconnected was in fact called on one of the
sockets in the accept filter; below is your patch slightly modified so it
does this.  I have tested it and was able to connect(2) until I ran out
of file descriptors.

Cheers,
Timo Buhrmester


diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 58335ec..99a6467 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -262,8 +262,37 @@ sonewconn(struct socket *head, bool soready)
 	KASSERT(solocked(head));
 
 	if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) {
-		/* Listen queue overflow. */
-		return NULL;
+		/*
+		 * Listen queue overflow.  If there is an accept filter
+		 * active, pass through the oldest cxn it's handling.
+		 */
+		if (head->so_accf == NULL) {
+			return NULL;
+		} else {
+			struct socket *so2, *next;
+
+			/* Pass the oldest connection waiting in the
+			   accept filter */
+			for (so2 = TAILQ_FIRST(&head->so_q0);
+			     so2 != NULL; so2 = next) {
+				next = TAILQ_NEXT(so2, so_qe);
+				if (so2->so_upcall == NULL) {
+					continue;
+				}
+				so2->so_upcall = NULL;
+				so2->so_upcallarg = NULL;
+				so2->so_options &= ~SO_ACCEPTFILTER;
+				so2->so_rcv.sb_flags &= ~SB_UPCALL;
+				soisconnected(so2);
+				break;
+			}
+
+			/* If nothing was nudged out of the acept filter, bail
+			 * out; otherwise proceed allocating the socket. */
+			if (so2 == NULL) {
+				return NULL;
+			}
+		}
 	}
 	if ((head->so_options & SO_ACCEPTFILTER) != 0) {
 		soready = false;


Home | Main Index | Thread Index | Old Index