summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/relayd/control.c')
-rw-r--r--usr.sbin/relayd/control.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/usr.sbin/relayd/control.c b/usr.sbin/relayd/control.c
index cdb4f0b063d..5cc6e60e04f 100644
--- a/usr.sbin/relayd/control.c
+++ b/usr.sbin/relayd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.40 2011/05/20 09:43:53 reyk Exp $ */
+/* $OpenBSD: control.c,v 1.41 2012/04/11 08:25:26 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -41,7 +41,7 @@
struct ctl_connlist ctl_conns;
void control_accept(int, short, void *);
-void control_close(int);
+void control_close(int, struct control_sock *);
int
control_init(struct privsep *ps, struct control_sock *cs)
@@ -115,9 +115,10 @@ control_listen(struct control_sock *cs)
return (-1);
}
- event_set(&cs->cs_ev, cs->cs_fd, EV_READ | EV_PERSIST,
- control_accept, cs->cs_env);
+ event_set(&cs->cs_ev, cs->cs_fd, EV_READ,
+ control_accept, cs);
event_add(&cs->cs_ev, NULL);
+ evtimer_set(&cs->cs_evt, control_accept, cs);
return (0);
}
@@ -127,6 +128,9 @@ control_cleanup(struct control_sock *cs)
{
if (cs->cs_name == NULL)
return;
+ event_del(&cs->cs_ev);
+ if (evtimer_pending(&cs->cs_evt, NULL))
+ event_del(&cs->cs_evt);
(void)unlink(cs->cs_name);
}
@@ -138,12 +142,25 @@ control_accept(int listenfd, short event, void *arg)
socklen_t len;
struct sockaddr_un sun;
struct ctl_conn *c;
- struct relayd *env = arg;
+ struct control_sock *cs = arg;
+
+ event_add(&cs->cs_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(&cs->cs_ev);
+ evtimer_add(&cs->cs_evt, &evtpause);
+ } else if (errno != EWOULDBLOCK && errno != EINTR)
log_warn("%s: accept", __func__);
return;
}
@@ -160,7 +177,7 @@ control_accept(int listenfd, short event, void *arg)
c->iev.handler = control_dispatch_imsg;
c->iev.events = EV_READ;
event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events,
- c->iev.handler, env);
+ c->iev.handler, cs);
event_add(&c->iev.ev, NULL);
TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
@@ -179,7 +196,7 @@ control_connbyfd(int fd)
}
void
-control_close(int fd)
+control_close(int fd, struct control_sock *cs)
{
struct ctl_conn *c;
@@ -193,6 +210,13 @@ control_close(int fd)
event_del(&c->iev.ev);
close(c->iev.ibuf.fd);
+
+ /* Some file descriptors are available again. */
+ if (evtimer_pending(&cs->cs_evt, NULL)) {
+ evtimer_del(&cs->cs_evt);
+ event_add(&cs->cs_ev, NULL);
+ }
+
free(c);
}
@@ -200,12 +224,13 @@ control_close(int fd)
void
control_dispatch_imsg(int fd, short event, void *arg)
{
+ struct control_sock *cs = (struct control_sock *)arg;
struct ctl_conn *c;
struct imsg imsg;
struct ctl_id id;
int n;
int verbose;
- struct relayd *env = arg;
+ struct relayd *env = cs->cs_env;
if ((c = control_connbyfd(fd)) == NULL) {
log_warn("%s: fd %d not found", __func__, fd);
@@ -214,21 +239,21 @@ control_dispatch_imsg(int fd, short event, void *arg)
if (event & EV_READ) {
if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
- control_close(fd);
+ control_close(fd, cs);
return;
}
}
if (event & EV_WRITE) {
if (msgbuf_write(&c->iev.ibuf.w) < 0) {
- control_close(fd);
+ control_close(fd, cs);
return;
}
}
for (;;) {
if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
- control_close(fd);
+ control_close(fd, cs);
return;
}
@@ -239,7 +264,7 @@ control_dispatch_imsg(int fd, short event, void *arg)
log_debug("%s: unexpected imsg %d",
__func__, imsg.hdr.type);
imsg_free(&imsg);
- control_close(fd);
+ control_close(fd, cs);
return;
}