diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2012-04-11 06:16:15 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2012-04-11 06:16:15 +0000 |
commit | 5af4ec4bc4f21fa63fbea2e34a9ea4d07c8423b0 (patch) | |
tree | 44abedbd325c35a1997d9558d3a55a10a2d53158 /usr.bin/tmux/server.c | |
parent | 61de1370078d8018aa3697f8700e90150a0e97f0 (diff) |
Stop accepting new clients for 1 second on EMFILE/ENFILE. Based on
ongoing fixes to other daemons by Theo.
Diffstat (limited to 'usr.bin/tmux/server.c')
-rw-r--r-- | usr.bin/tmux/server.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/usr.bin/tmux/server.c b/usr.bin/tmux/server.c index e990955ce72..2efe0f54d5e 100644 --- a/usr.bin/tmux/server.c +++ b/usr.bin/tmux/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.103 2012/03/09 09:57:40 nicm Exp $ */ +/* $OpenBSD: server.c,v 1.104 2012/04/11 06:16:14 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -191,9 +191,7 @@ server_start(int lockfd, char *lockfile) } cfg_finished = 1; - event_set(&server_ev_accept, - server_fd, EV_READ|EV_PERSIST, server_accept_callback, NULL); - event_add(&server_ev_accept, NULL); + server_add_accept(0); memset(&tv, 0, sizeof tv); tv.tv_sec = 1; @@ -337,6 +335,7 @@ server_accept_callback(int fd, short events, unused void *data) socklen_t slen = sizeof sa; int newfd; + server_add_accept(0); if (!(events & EV_READ)) return; @@ -344,6 +343,11 @@ server_accept_callback(int fd, short events, unused void *data) if (newfd == -1) { if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED) return; + if (errno == ENFILE || errno == EMFILE) { + /* Delete and don't try again for 1 second. */ + server_add_accept(1); + return; + } fatal("accept failed"); } if (server_shutdown) { @@ -353,6 +357,29 @@ server_accept_callback(int fd, short events, unused void *data) server_client_create(newfd); } +/* + * Add accept event. If timeout is nonzero, add as a timeout instead of a read + * event - used to backoff when running out of file descriptors. + */ +void +server_add_accept(int timeout) +{ + struct timeval tv = { timeout, 0 }; + + if (event_initialized(&server_ev_accept)) + event_del(&server_ev_accept); + + if (timeout == 0) { + event_set(&server_ev_accept, + server_fd, EV_READ, server_accept_callback, NULL); + event_add(&server_ev_accept, NULL); + } else { + event_set(&server_ev_accept, + server_fd, EV_TIMEOUT, server_accept_callback, NULL); + event_add(&server_ev_accept, &tv); + } +} + /* Signal handler. */ /* ARGSUSED */ void @@ -370,9 +397,7 @@ server_signal_callback(int sig, unused short events, unused void *data) event_del(&server_ev_accept); close(server_fd); server_fd = server_create_socket(); - event_set(&server_ev_accept, server_fd, - EV_READ|EV_PERSIST, server_accept_callback, NULL); - event_add(&server_ev_accept, NULL); + server_add_accept(0); break; } } |