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);
