diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2012-04-10 07:56:55 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2012-04-10 07:56:55 +0000 |
commit | 11f779a7907d0dbca7653b462a05ca2a2778e1ce (patch) | |
tree | a3324188e8f7d0ae82834625e9ec19945ac4a692 /usr.sbin/dvmrpd | |
parent | e28e185032a9204a235a0b9df0f4ab444af013e7 (diff) |
Handle file descriptor exhaustion in the accept() case.
ok claudio
Diffstat (limited to 'usr.sbin/dvmrpd')
-rw-r--r-- | usr.sbin/dvmrpd/control.c | 30 | ||||
-rw-r--r-- | usr.sbin/dvmrpd/control.h | 3 |
2 files changed, 29 insertions, 4 deletions
diff --git a/usr.sbin/dvmrpd/control.c b/usr.sbin/dvmrpd/control.c index b655306426b..2e2b52370ab 100644 --- a/usr.sbin/dvmrpd/control.c +++ b/usr.sbin/dvmrpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.14 2010/09/02 14:03:21 sobrado Exp $ */ +/* $OpenBSD: control.c,v 1.15 2012/04/10 07:56:54 deraadt Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -93,9 +93,10 @@ control_listen(void) return (-1); } - event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST, + event_set(&control_state.ev, control_state.fd, EV_READ, control_accept, NULL); event_add(&control_state.ev, NULL); + evtimer_set(&control_state.evt, control_accept, NULL); return (0); } @@ -103,6 +104,9 @@ control_listen(void) void control_cleanup(void) { + event_del(&control_state.ev); + if (evtimer_pending(&control_state.evt, NULL)) + event_del(&control_state.evt); unlink(DVMRPD_SOCKET); } @@ -115,10 +119,23 @@ control_accept(int listenfd, short event, void *bula) struct sockaddr_un sun; struct ctl_conn *c; + event_add(&control_state.ev, NULL); + if ((event & EV_TIMEOUT)) + return; + len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { - if (errno != EWOULDBLOCK && errno != EINTR) + /* + * Pause accept if we are out of file descriptors, or + * libevent will haunt us here too. + */ + if (errno == ENFILE || errno == EMFILE) { + struct timeval evtpause = { 1, 0 }; + + event_del(&control_state.ev); + evtimer_add(&control_state.evt, &evtpause); + } else if (errno != EWOULDBLOCK && errno != EINTR) log_warn("control_accept: accept"); return; } @@ -180,6 +197,13 @@ control_close(int fd) event_del(&c->iev.ev); close(c->iev.ibuf.fd); + + /* Some file descriptors are available again. */ + if (evtimer_pending(&control_state.evt, NULL)) { + evtimer_del(&control_state.evt); + event_add(&control_state.ev, NULL); + } + free(c); } diff --git a/usr.sbin/dvmrpd/control.h b/usr.sbin/dvmrpd/control.h index 7840bf9b1a6..6eeef82e7e6 100644 --- a/usr.sbin/dvmrpd/control.h +++ b/usr.sbin/dvmrpd/control.h @@ -1,4 +1,4 @@ -/* $OpenBSD: control.h,v 1.2 2009/06/06 07:52:04 pyr Exp $ */ +/* $OpenBSD: control.h,v 1.3 2012/04/10 07:56:54 deraadt Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -25,6 +25,7 @@ struct { struct event ev; + struct event evt; int fd; } control_state; |