In accept1(), falloc() is called after the process has awoken, but prior
to removing the connection from the queue. The problem here is that falloc() may block and this would allow another process to accept the connection instead. If this happens to leave the queue empty, then the system will panic with an "accept: nothing queued". Also changed a wakeup() to a wakeup_one() to avoid the "thundering herd" problem on new connections in Apache (or any other application that has multiple processes blocked in accept() for the same socket).
This commit is contained in:
parent
57862eed22
commit
a91b87211d
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: uipc_socket2.c,v 1.21 1997/02/19 19:15:43 wollman Exp $
|
||||
* $Id: uipc_socket2.c,v 1.22 1997/02/24 20:30:57 wollman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -111,9 +111,9 @@ soisconnected(so)
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
so->so_state |= SS_COMP;
|
||||
sorwakeup(head);
|
||||
wakeup((caddr_t)&head->so_timeo);
|
||||
wakeup_one(&head->so_timeo);
|
||||
} else {
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
wakeup(&so->so_timeo);
|
||||
sorwakeup(so);
|
||||
sowwakeup(so);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: uipc_socket2.c,v 1.21 1997/02/19 19:15:43 wollman Exp $
|
||||
* $Id: uipc_socket2.c,v 1.22 1997/02/24 20:30:57 wollman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -111,9 +111,9 @@ soisconnected(so)
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
so->so_state |= SS_COMP;
|
||||
sorwakeup(head);
|
||||
wakeup((caddr_t)&head->so_timeo);
|
||||
wakeup_one(&head->so_timeo);
|
||||
} else {
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
wakeup(&so->so_timeo);
|
||||
sorwakeup(so);
|
||||
sowwakeup(so);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
|
||||
* $Id: uipc_syscalls.c,v 1.22 1997/02/22 09:39:29 peter Exp $
|
||||
* $Id: uipc_syscalls.c,v 1.23 1997/03/23 03:36:32 bde Exp $
|
||||
*/
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
@ -208,20 +208,36 @@ accept1(p, uap, retval, compat)
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we know that there is at least one connection
|
||||
* ready to be accepted. Remove it from the queue prior to
|
||||
* allocating the file descriptor for it since falloc() may
|
||||
* block allowing another process to accept the connection
|
||||
* instead.
|
||||
*/
|
||||
so = head->so_comp.tqh_first;
|
||||
TAILQ_REMOVE(&head->so_comp, so, so_list);
|
||||
head->so_qlen--;
|
||||
|
||||
fflag = fp->f_flag;
|
||||
error = falloc(p, &fp, retval);
|
||||
if (error) {
|
||||
/*
|
||||
* Probably ran out of file descriptors. Put the
|
||||
* unaccepted connection back onto the queue and
|
||||
* do another wakeup so some other process might
|
||||
* have a chance at it.
|
||||
*/
|
||||
TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
|
||||
head->so_qlen++;
|
||||
wakeup_one(&head->so_timeo);
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
so = head->so_comp.tqh_first;
|
||||
if (so == NULL)
|
||||
panic("accept: nothing queued");
|
||||
TAILQ_REMOVE(&head->so_comp, so, so_list);
|
||||
so->so_state &= ~SS_COMP;
|
||||
so->so_head = NULL;
|
||||
head->so_qlen--;
|
||||
|
||||
fp->f_type = DTYPE_SOCKET;
|
||||
fp->f_flag = fflag;
|
||||
|
Loading…
x
Reference in New Issue
Block a user