- djm@cvs.openbsd.org 2012/04/11 13:16:19
[channels.c channels.h clientloop.c serverloop.c] don't spin in accept() when out of fds (ENFILE/ENFILE) - back off for a while; ok deraadt@ markus@
This commit is contained in:
parent
c6081482b2
commit
a6508753db
|
@ -17,6 +17,10 @@
|
|||
[channels.c channels.h servconf.c]
|
||||
Add PermitOpen none option based on patch from Loganaden Velvindron
|
||||
(bz #1949). ok djm@
|
||||
- djm@cvs.openbsd.org 2012/04/11 13:16:19
|
||||
[channels.c channels.h clientloop.c serverloop.c]
|
||||
don't spin in accept() when out of fds (ENFILE/ENFILE) - back off for a
|
||||
while; ok deraadt@ markus@
|
||||
|
||||
20120420
|
||||
- (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
|
||||
|
|
52
channels.c
52
channels.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: channels.c,v 1.316 2012/03/29 23:54:36 dtucker Exp $ */
|
||||
/* $OpenBSD: channels.c,v 1.317 2012/04/11 13:16:19 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -311,6 +311,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
|||
c->istate = CHAN_INPUT_OPEN;
|
||||
c->flags = 0;
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0);
|
||||
c->notbefore = 0;
|
||||
c->self = found;
|
||||
c->type = type;
|
||||
c->ctype = ctype;
|
||||
|
@ -1339,6 +1340,8 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
|||
}
|
||||
if (newsock < 0) {
|
||||
error("accept: %.100s", strerror(errno));
|
||||
if (errno == EMFILE || errno == ENFILE)
|
||||
c->notbefore = time(NULL) + 1;
|
||||
return;
|
||||
}
|
||||
set_nodelay(newsock);
|
||||
|
@ -1482,6 +1485,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
|||
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
|
||||
if (newsock < 0) {
|
||||
error("accept: %.100s", strerror(errno));
|
||||
if (errno == EMFILE || errno == ENFILE)
|
||||
c->notbefore = time(NULL) + 1;
|
||||
return;
|
||||
}
|
||||
set_nodelay(newsock);
|
||||
|
@ -1514,7 +1519,10 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
|||
addrlen = sizeof(addr);
|
||||
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
|
||||
if (newsock < 0) {
|
||||
error("accept from auth socket: %.100s", strerror(errno));
|
||||
error("accept from auth socket: %.100s",
|
||||
strerror(errno));
|
||||
if (errno == EMFILE || errno == ENFILE)
|
||||
c->notbefore = time(NULL) + 1;
|
||||
return;
|
||||
}
|
||||
nc = channel_new("accepted auth socket",
|
||||
|
@ -1917,6 +1925,8 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
|||
if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
|
||||
&addrlen)) == -1) {
|
||||
error("%s accept: %s", __func__, strerror(errno));
|
||||
if (errno == EMFILE || errno == ENFILE)
|
||||
c->notbefore = time(NULL) + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2067,16 +2077,21 @@ channel_garbage_collect(Channel *c)
|
|||
}
|
||||
|
||||
static void
|
||||
channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
|
||||
channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset,
|
||||
time_t *unpause_secs)
|
||||
{
|
||||
static int did_init = 0;
|
||||
u_int i, oalloc;
|
||||
Channel *c;
|
||||
time_t now;
|
||||
|
||||
if (!did_init) {
|
||||
channel_handler_init();
|
||||
did_init = 1;
|
||||
}
|
||||
now = time(NULL);
|
||||
if (unpause_secs != NULL)
|
||||
*unpause_secs = 0;
|
||||
for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
|
||||
c = channels[i];
|
||||
if (c == NULL)
|
||||
|
@ -2087,10 +2102,30 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
|
|||
else
|
||||
continue;
|
||||
}
|
||||
if (ftab[c->type] != NULL)
|
||||
(*ftab[c->type])(c, readset, writeset);
|
||||
if (ftab[c->type] != NULL) {
|
||||
/*
|
||||
* Run handlers that are not paused.
|
||||
*/
|
||||
if (c->notbefore <= now)
|
||||
(*ftab[c->type])(c, readset, writeset);
|
||||
else if (unpause_secs != NULL) {
|
||||
/*
|
||||
* Collect the time that the earliest
|
||||
* channel comes off pause.
|
||||
*/
|
||||
debug3("%s: chan %d: skip for %d more seconds",
|
||||
__func__, c->self,
|
||||
(int)(c->notbefore - now));
|
||||
if (*unpause_secs == 0 ||
|
||||
(c->notbefore - now) < *unpause_secs)
|
||||
*unpause_secs = c->notbefore - now;
|
||||
}
|
||||
}
|
||||
channel_garbage_collect(c);
|
||||
}
|
||||
if (unpause_secs != NULL && *unpause_secs != 0)
|
||||
debug3("%s: first channel unpauses in %d seconds",
|
||||
__func__, (int)*unpause_secs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2099,7 +2134,7 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
|
|||
*/
|
||||
void
|
||||
channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
||||
u_int *nallocp, int rekeying)
|
||||
u_int *nallocp, int *minwait_secs, int rekeying)
|
||||
{
|
||||
u_int n, sz, nfdset;
|
||||
|
||||
|
@ -2122,7 +2157,8 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
|||
memset(*writesetp, 0, sz);
|
||||
|
||||
if (!rekeying)
|
||||
channel_handler(channel_pre, *readsetp, *writesetp);
|
||||
channel_handler(channel_pre, *readsetp, *writesetp,
|
||||
minwait_secs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2132,7 +2168,7 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
|||
void
|
||||
channel_after_select(fd_set *readset, fd_set *writeset)
|
||||
{
|
||||
channel_handler(channel_post, readset, writeset);
|
||||
channel_handler(channel_post, readset, writeset, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: channels.h,v 1.110 2012/03/29 23:54:36 dtucker Exp $ */
|
||||
/* $OpenBSD: channels.h,v 1.111 2012/04/11 13:16:19 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -105,6 +105,7 @@ struct Channel {
|
|||
int wfd_isatty; /* wfd is a tty */
|
||||
int client_tty; /* (client) TTY has been requested */
|
||||
int force_drain; /* force close on iEOF */
|
||||
time_t notbefore; /* Pause IO until deadline (time_t) */
|
||||
int delayed; /* post-select handlers for newly created
|
||||
* channels are delayed until the first call
|
||||
* to a matching pre-select handler.
|
||||
|
@ -238,7 +239,8 @@ void channel_input_status_confirm(int, u_int32_t, void *);
|
|||
|
||||
/* file descriptor handling (read/write) */
|
||||
|
||||
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int);
|
||||
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*,
|
||||
time_t*, int);
|
||||
void channel_after_select(fd_set *, fd_set *);
|
||||
void channel_output_poll(void);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: clientloop.c,v 1.238 2012/01/18 21:46:43 dtucker Exp $ */
|
||||
/* $OpenBSD: clientloop.c,v 1.239 2012/04/11 13:16:19 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -583,10 +583,12 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
|
|||
{
|
||||
struct timeval tv, *tvp;
|
||||
int timeout_secs;
|
||||
time_t minwait_secs;
|
||||
int ret;
|
||||
|
||||
/* Add any selections by the channel mechanism. */
|
||||
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
|
||||
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
|
||||
&minwait_secs, rekeying);
|
||||
|
||||
if (!compat20) {
|
||||
/* Read from the connection, unless our buffers are full. */
|
||||
|
@ -639,6 +641,8 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
|
|||
if (timeout_secs < 0)
|
||||
timeout_secs = 0;
|
||||
}
|
||||
if (minwait_secs != 0)
|
||||
timeout_secs = MIN(timeout_secs, (int)minwait_secs);
|
||||
if (timeout_secs == INT_MAX)
|
||||
tvp = NULL;
|
||||
else {
|
||||
|
|
14
serverloop.c
14
serverloop.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: serverloop.c,v 1.160 2011/05/15 08:09:01 djm Exp $ */
|
||||
/* $OpenBSD: serverloop.c,v 1.161 2012/04/11 13:16:19 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -281,9 +281,18 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
|||
{
|
||||
struct timeval tv, *tvp;
|
||||
int ret;
|
||||
time_t minwait_secs;
|
||||
int client_alive_scheduled = 0;
|
||||
int program_alive_scheduled = 0;
|
||||
|
||||
/* Allocate and update select() masks for channel descriptors. */
|
||||
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
|
||||
&minwait_secs, 0);
|
||||
|
||||
if (minwait_secs != 0)
|
||||
max_time_milliseconds = MIN(max_time_milliseconds,
|
||||
(u_int)minwait_secs * 1000);
|
||||
|
||||
/*
|
||||
* if using client_alive, set the max timeout accordingly,
|
||||
* and indicate that this particular timeout was for client
|
||||
|
@ -298,9 +307,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
|||
max_time_milliseconds = options.client_alive_interval * 1000;
|
||||
}
|
||||
|
||||
/* Allocate and update select() masks for channel descriptors. */
|
||||
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0);
|
||||
|
||||
if (compat20) {
|
||||
#if 0
|
||||
/* wrong: bad condition XXX */
|
||||
|
|
Loading…
Reference in New Issue