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