Sync OpenBSD patchset 1092:

Stop accepting new clients for 1 second on EMFILE/ENFILE. Based on
ongoing fixes to other daemons by Theo.
This commit is contained in:
Tiago Cunha 2012-04-12 12:43:40 +00:00
parent ce67a44a94
commit bae2701289
3 changed files with 34 additions and 6 deletions

View File

@ -190,6 +190,8 @@ server_client_lost(struct client *c)
ARRAY_ADD(&dead_clients, c); ARRAY_ADD(&dead_clients, c);
c->flags |= CLIENT_DEAD; c->flags |= CLIENT_DEAD;
server_add_accept(0); /* may be more file descriptors now */
recalculate_sizes(); recalculate_sizes();
server_check_unattached(); server_check_unattached();
server_update_socket(); server_update_socket();

View File

@ -192,9 +192,7 @@ server_start(int lockfd, char *lockfile)
} }
cfg_finished = 1; cfg_finished = 1;
event_set(&server_ev_accept, server_add_accept(0);
server_fd, EV_READ|EV_PERSIST, server_accept_callback, NULL);
event_add(&server_ev_accept, NULL);
memset(&tv, 0, sizeof tv); memset(&tv, 0, sizeof tv);
tv.tv_sec = 1; tv.tv_sec = 1;
@ -338,6 +336,7 @@ server_accept_callback(int fd, short events, unused void *data)
socklen_t slen = sizeof sa; socklen_t slen = sizeof sa;
int newfd; int newfd;
server_add_accept(0);
if (!(events & EV_READ)) if (!(events & EV_READ))
return; return;
@ -345,6 +344,11 @@ server_accept_callback(int fd, short events, unused void *data)
if (newfd == -1) { if (newfd == -1) {
if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED) if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
return; return;
if (errno == ENFILE || errno == EMFILE) {
/* Delete and don't try again for 1 second. */
server_add_accept(1);
return;
}
fatal("accept failed"); fatal("accept failed");
} }
if (server_shutdown) { if (server_shutdown) {
@ -354,6 +358,29 @@ server_accept_callback(int fd, short events, unused void *data)
server_client_create(newfd); 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. */ /* Signal handler. */
/* ARGSUSED */ /* ARGSUSED */
void void
@ -371,9 +398,7 @@ server_signal_callback(int sig, unused short events, unused void *data)
event_del(&server_ev_accept); event_del(&server_ev_accept);
close(server_fd); close(server_fd);
server_fd = server_create_socket(); server_fd = server_create_socket();
event_set(&server_ev_accept, server_fd, server_add_accept(0);
EV_READ|EV_PERSIST, server_accept_callback, NULL);
event_add(&server_ev_accept, NULL);
break; break;
} }
} }

1
tmux.h
View File

@ -1709,6 +1709,7 @@ extern struct clients dead_clients;
extern struct paste_stack global_buffers; extern struct paste_stack global_buffers;
int server_start(int, char *); int server_start(int, char *);
void server_update_socket(void); void server_update_socket(void);
void server_add_accept(int);
/* server-client.c */ /* server-client.c */
void server_client_create(int); void server_client_create(int);