diff options
author | Tiago Cunha <tcunha@gmx.com> | 2012-04-12 12:43:40 +0000 |
---|---|---|
committer | Tiago Cunha <tcunha@gmx.com> | 2012-04-12 12:43:40 +0000 |
commit | bae27012893a2b1f181f304088b206bd356347b4 (patch) | |
tree | 545db736c606ac9f63385be9f49052adadd16bc2 | |
parent | ce67a44a94a9d524ec8f45a452dde37fd7ea991f (diff) | |
download | rtmux-bae27012893a2b1f181f304088b206bd356347b4.tar.gz rtmux-bae27012893a2b1f181f304088b206bd356347b4.tar.bz2 rtmux-bae27012893a2b1f181f304088b206bd356347b4.zip |
Sync OpenBSD patchset 1092:
Stop accepting new clients for 1 second on EMFILE/ENFILE. Based on
ongoing fixes to other daemons by Theo.
-rw-r--r-- | server-client.c | 2 | ||||
-rw-r--r-- | server.c | 37 | ||||
-rw-r--r-- | tmux.h | 1 |
3 files changed, 34 insertions, 6 deletions
diff --git a/server-client.c b/server-client.c index 90ec5eb1..44a5e13f 100644 --- a/server-client.c +++ b/server-client.c @@ -190,6 +190,8 @@ server_client_lost(struct client *c) ARRAY_ADD(&dead_clients, c); c->flags |= CLIENT_DEAD; + server_add_accept(0); /* may be more file descriptors now */ + recalculate_sizes(); server_check_unattached(); server_update_socket(); @@ -192,9 +192,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; @@ -338,6 +336,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; @@ -345,6 +344,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) { @@ -354,6 +358,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 @@ -371,9 +398,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; } } @@ -1709,6 +1709,7 @@ extern struct clients dead_clients; extern struct paste_stack global_buffers; int server_start(int, char *); void server_update_socket(void); +void server_add_accept(int); /* server-client.c */ void server_client_create(int); |