summaryrefslogtreecommitdiff
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
parente28e185032a9204a235a0b9df0f4ab444af013e7 (diff)
Handle file descriptor exhaustion in the accept() case.
ok claudio
-rw-r--r--usr.sbin/dvmrpd/control.c30
-rw-r--r--usr.sbin/dvmrpd/control.h3
-rw-r--r--usr.sbin/ospf6d/control.c30
-rw-r--r--usr.sbin/ospf6d/control.h3
-rw-r--r--usr.sbin/ospfd/control.c35
-rw-r--r--usr.sbin/ospfd/control.h3
-rw-r--r--usr.sbin/ripd/control.c30
-rw-r--r--usr.sbin/ripd/control.h3
8 files changed, 119 insertions, 18 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;
diff --git a/usr.sbin/ospf6d/control.c b/usr.sbin/ospf6d/control.c
index 61327fc5635..a6e2107f3d6 100644
--- a/usr.sbin/ospf6d/control.c
+++ b/usr.sbin/ospf6d/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.16 2010/07/01 19:47:04 bluhm Exp $ */
+/* $OpenBSD: control.c,v 1.17 2012/04/10 07:56:50 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -91,9 +91,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);
}
@@ -101,6 +102,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(OSPF6D_SOCKET);
}
@@ -113,10 +117,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;
}
@@ -178,6 +195,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/ospf6d/control.h b/usr.sbin/ospf6d/control.h
index 0d8d1e2805c..d552d3e1b67 100644
--- a/usr.sbin/ospf6d/control.h
+++ b/usr.sbin/ospf6d/control.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.h,v 1.2 2009/06/06 09:02:46 eric Exp $ */
+/* $OpenBSD: control.h,v 1.3 2012/04/10 07:56:50 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;
diff --git a/usr.sbin/ospfd/control.c b/usr.sbin/ospfd/control.c
index 44157b5f659..a06a9b4e9b4 100644
--- a/usr.sbin/ospfd/control.c
+++ b/usr.sbin/ospfd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.35 2011/05/09 12:24:41 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.36 2012/04/10 07:56:54 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -92,9 +92,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);
}
@@ -102,8 +103,12 @@ control_listen(void)
void
control_cleanup(char *path)
{
- if (path)
- unlink(path);
+ if (path == NULL)
+ return;
+ event_del(&control_state.ev);
+ if (evtimer_pending(&control_state.evt, NULL))
+ event_del(&control_state.evt);
+ unlink(path);
}
/* ARGSUSED */
@@ -115,10 +120,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 +198,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/ospfd/control.h b/usr.sbin/ospfd/control.h
index b439e645938..8f70ef63ebc 100644
--- a/usr.sbin/ospfd/control.h
+++ b/usr.sbin/ospfd/control.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.h,v 1.4 2009/06/06 07:31:26 eric Exp $ */
+/* $OpenBSD: control.h,v 1.5 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;
diff --git a/usr.sbin/ripd/control.c b/usr.sbin/ripd/control.c
index a38edcb4350..f3ea65d4ff1 100644
--- a/usr.sbin/ripd/control.c
+++ b/usr.sbin/ripd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.15 2010/05/14 11:52:19 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.16 2012/04/10 07:56:54 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -92,9 +92,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);
}
@@ -102,6 +103,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(RIPD_SOCKET);
}
@@ -114,10 +118,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;
}
@@ -179,6 +196,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/ripd/control.h b/usr.sbin/ripd/control.h
index 23240d367ae..6eeef82e7e6 100644
--- a/usr.sbin/ripd/control.h
+++ b/usr.sbin/ripd/control.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.h,v 1.2 2009/06/06 08:20:55 eric 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;