summaryrefslogtreecommitdiffstats
path: root/dhcpcd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-09-05 12:28:05 +0000
committerRoy Marples <roy@marples.name>2014-09-05 12:28:05 +0000
commit923e118097c5296c5e94b5518d8b06c67c2f4b52 (patch)
tree0bf095f0aa39591a067c5db653cd351e46e519ce /dhcpcd.c
parenta0011b993364c6ac24e4e5e534ac07fcef2d02c3 (diff)
downloaddhcpcd-923e118097c5296c5e94b5518d8b06c67c2f4b52.tar.xz
Implement a send queue for each control fd.
Only one call to write(2) should be performed for each POLLOUT check via poll(2) so we should never see EAGAIN when writing to control sockets ever again. Each fd queue is limited to 100 entries so we don't OOM with badly written control subscribers.
Diffstat (limited to 'dhcpcd.c')
-rw-r--r--dhcpcd.c55
1 files changed, 8 insertions, 47 deletions
diff --git a/dhcpcd.c b/dhcpcd.c
index 23142094..13ece6a9 100644
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1047,42 +1047,6 @@ signal_init(void (*func)(int, siginfo_t *, void *), sigset_t *oldset)
#endif
static void
-dhcpcd_version(void *arg)
-{
- struct fd_list *fd = arg;
- size_t len;
- struct iovec iov[2];
-
- len = strlen(VERSION) + 1;
- iov[0].iov_base = &len;
- iov[0].iov_len = sizeof(ssize_t);
- iov[1].iov_base = UNCONST(VERSION);
- iov[1].iov_len = len;
- if (writev(fd->fd, iov, 2) == -1)
- syslog(LOG_ERR, "%s: writev: %m", __func__);
- else
- eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
-}
-
-static void
-dhcpcd_getconfigfile(void *arg)
-{
- struct fd_list *fd = arg;
- size_t len;
- struct iovec iov[2];
-
- len = strlen(fd->ctx->cffile) + 1;
- iov[0].iov_base = &len;
- iov[0].iov_len = sizeof(ssize_t);
- iov[1].iov_base = UNCONST(fd->ctx->cffile);
- iov[1].iov_len = len;
- if (writev(fd->fd, iov, 2) == -1)
- syslog(LOG_ERR, "%s: writev: %m", __func__);
- else
- eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
-}
-
-static void
dhcpcd_getinterfaces(void *arg)
{
struct fd_list *fd = arg;
@@ -1101,11 +1065,11 @@ dhcpcd_getinterfaces(void *arg)
}
if (write(fd->fd, &len, sizeof(len)) != sizeof(len))
return;
+ eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
- if (send_interface(fd->fd, ifp) == -1)
+ if (send_interface(fd, ifp) == -1)
syslog(LOG_ERR, "send_interface %d: %m", fd->fd);
}
- eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
}
int
@@ -1124,13 +1088,11 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
* expected reply we should be safely able just to change the
* write callback on the fd */
if (strcmp(*argv, "--version") == 0) {
- eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
- dhcpcd_version, fd);
- return 0;
+ return control_queue(fd, UNCONST(VERSION),
+ strlen(VERSION) + 1, 0);
} else if (strcmp(*argv, "--getconfigfile") == 0) {
- eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
- dhcpcd_getconfigfile, fd);
- return 0;
+ return control_queue(fd, UNCONST(fd->ctx->cffile),
+ strlen(fd->ctx->cffile) + 1, 0);
} else if (strcmp(*argv, "--getinterfaces") == 0) {
eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
dhcpcd_getinterfaces, fd);
@@ -1146,10 +1108,8 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
for (opt = 0; opt < argc; opt++)
len += strlen(argv[opt]) + 1;
tmp = malloc(len);
- if (tmp == NULL) {
- syslog(LOG_ERR, "%s: %m", __func__);
+ if (tmp == NULL)
return -1;
- }
p = tmp;
for (opt = 0; opt < argc; opt++) {
l = strlen(argv[opt]);
@@ -1256,6 +1216,7 @@ main(int argc, char **argv)
ifo = NULL;
ctx.cffile = CONFIG;
ctx.pid_fd = ctx.control_fd = ctx.link_fd = -1;
+ TAILQ_INIT(&ctx.control_fds);
#ifdef PLUGIN_DEV
ctx.dev_fd = -1;
#endif