Note: this is the second version of this patch. Apply by doing cd /usr/src/sys patch -p0 < accept.patch And then rebuild your kernel. Index: sys/socketvar.h =================================================================== RCS file: /cvs/src/sys/sys/socketvar.h,v retrieving revision 1.15 diff -u -r1.15 socketvar.h --- socketvar.h 1999/02/18 22:56:57 1.15 +++ socketvar.h 1999/02/19 03:36:15 @@ -113,6 +113,7 @@ #define SS_CANTSENDMORE 0x010 /* can't send more data to peer */ #define SS_CANTRCVMORE 0x020 /* can't receive more data from peer */ #define SS_RCVATMARK 0x040 /* at mark on input */ +#define SS_ISDISCONNECTED 0x800 /* socket disconnected from peer */ #define SS_PRIV 0x080 /* privileged for broadcast, raw... */ #define SS_NBIO 0x100 /* non-blocking ops */ Index: kern/uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.25 diff -u -r1.25 uipc_socket.c --- uipc_socket.c 1999/02/18 22:56:58 1.25 +++ uipc_socket.c 1999/02/19 03:36:23 @@ -156,9 +156,13 @@ if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; if (so->so_head) { - if (!soqremque(so, 0) && !soqremque(so, 1)) - panic("sofree dq"); - so->so_head = 0; + /* + * We must not decommission a socket that's on the accept(2) + * queue. If we do, then accept(2) may hang after select(2) + * indicated that the listening socket was ready. + */ + if (!soqremque(so, 0)) + return; } sbrelease(&so->so_snd); sorflush(so); @@ -174,14 +178,19 @@ soclose(so) register struct socket *so; { + struct socket *so2; int s = splsoftnet(); /* conservative */ int error = 0; if (so->so_options & SO_ACCEPTCONN) { - while (so->so_q0) - (void) soabort(so->so_q0); - while (so->so_q) - (void) soabort(so->so_q); + while ((so2 = so->so_q0) != NULL) { + (void) soqremque(so2, 0); + (void) soabort(so2); + } + while ((so2 = so->so_q) != NULL) { + (void) soqremque(so2, 1); + (void) soabort(so2); + } } if (so->so_pcb == 0) goto discard; @@ -237,12 +246,14 @@ struct mbuf *nam; { int s = splsoftnet(); - int error; + int error = 0; if ((so->so_state & SS_NOFDREF) == 0) panic("soaccept: !NOFDREF"); so->so_state &= ~SS_NOFDREF; - error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL, nam, NULL); + if ((so->so_state & SS_ISDISCONNECTED) == 0) + error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL, + nam, NULL); splx(s); return (error); } Index: kern/uipc_socket2.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket2.c,v retrieving revision 1.9 diff -u -r1.9 uipc_socket2.c --- uipc_socket2.c 1999/02/18 22:56:58 1.9 +++ uipc_socket2.c 1999/02/19 03:36:28 @@ -135,7 +135,7 @@ { so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); - so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); + so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED); wakeup((caddr_t)&so->so_timeo); sowwakeup(so); sorwakeup(so);