summaryrefslogtreecommitdiff
path: root/usr.sbin/dvmrpd
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2012-04-10 07:56:55 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2012-04-10 07:56:55 +0000
commit11f779a7907d0dbca7653b462a05ca2a2778e1ce (patch)
treea3324188e8f7d0ae82834625e9ec19945ac4a692 /usr.sbin/dvmrpd
parente28e185032a9204a235a0b9df0f4ab444af013e7 (diff)
Handle file descriptor exhaustion in the accept() case.
ok claudio
Diffstat (limited to 'usr.sbin/dvmrpd')
-rw-r--r--usr.sbin/dvmrpd/control.c30
-rw-r--r--usr.sbin/dvmrpd/control.h3
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;