From c32c88b642b8c65eb68b505e0783fd46b57fc6fa Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Wed, 8 Nov 2023 11:09:52 +0000 Subject: [PATCH] dhcpcd: Close fork_fd on hangup Closing it early results in zero length reads in some situations. Logging that we forked via the launcher process also make more sense and allows us to use log* functions. While here, handle error condtions better by forcing a return rather than handling an invalid state. Fixes #260. --- src/dhcpcd.c | 81 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 71e7d807..46c64b42 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -365,7 +365,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) return; #else int i; - unsigned int logopts = loggetopts(); if (ctx->options & DHCPCD_DAEMONISE && !(ctx->options & (DHCPCD_DAEMONISED | DHCPCD_NOWAITIP))) @@ -385,11 +384,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) !(ctx->options & DHCPCD_DAEMONISE)) return; - /* Don't use loginfo because this makes no sense in a log. */ - if (!(logopts & LOGERR_QUIET) && ctx->stderr_valid) - (void)fprintf(stderr, - "forked to background, child pid %d\n", getpid()); - #ifdef PRIVSEP ps_daemonised(ctx); #else @@ -400,9 +394,8 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) if (write(ctx->fork_fd, &i, sizeof(i)) == -1) logerr("write"); ctx->options |= DHCPCD_DAEMONISED; - eloop_event_delete(ctx->eloop, ctx->fork_fd); - close(ctx->fork_fd); - ctx->fork_fd = -1; + // dhcpcd_fork_cb will close the socket + shutdown(ctx->fork_fd, SHUT_RDWR); #endif } @@ -1822,31 +1815,6 @@ dhcpcd_readdump(struct dhcpcd_ctx *ctx) dhcpcd_readdump0, ctx); } -static void -dhcpcd_fork_cb(void *arg, unsigned short events) -{ - struct dhcpcd_ctx *ctx = arg; - int exit_code; - ssize_t len; - - if (!(events & ELE_READ)) - logerrx("%s: unexpected event 0x%04x", __func__, events); - - len = read(ctx->fork_fd, &exit_code, sizeof(exit_code)); - if (len == -1) { - logerr(__func__); - exit_code = EXIT_FAILURE; - } else if ((size_t)len < sizeof(exit_code)) { - logerrx("%s: truncated read %zd (expected %zu)", - __func__, len, sizeof(exit_code)); - exit_code = EXIT_FAILURE; - } - if (ctx->options & DHCPCD_FORKED) - eloop_exit(ctx->eloop, exit_code); - else - dhcpcd_signal_cb(exit_code, ctx); -} - static void dhcpcd_stderr_cb(void *arg, unsigned short events) { @@ -1871,6 +1839,51 @@ dhcpcd_stderr_cb(void *arg, unsigned short events) fprintf(stderr, "%s", log); } +static void +dhcpcd_fork_cb(void *arg, unsigned short events) +{ + struct dhcpcd_ctx *ctx = arg; + int exit_code; + ssize_t len; + + if (!(events & ELE_READ)) + logerrx("%s: unexpected event 0x%04x", __func__, events); + + len = read(ctx->fork_fd, &exit_code, sizeof(exit_code)); + if (len == -1) { + logerr(__func__); + eloop_exit(ctx->eloop, EXIT_FAILURE); + return; + } + if (len == 0) { + if (ctx->options & DHCPCD_FORKED) { + logerrx("%s: dhcpcd manager hungup", __func__); + eloop_exit(ctx->eloop, EXIT_FAILURE); + } else { + // Launcher exited + eloop_event_delete(ctx->eloop, ctx->fork_fd); + close(ctx->fork_fd); + ctx->fork_fd = -1; + } + return; + } + if ((size_t)len < sizeof(exit_code)) { + logerrx("%s: truncated read %zd (expected %zu)", + __func__, len, sizeof(exit_code)); + eloop_exit(ctx->eloop, EXIT_FAILURE); + return; + } + + if (ctx->options & DHCPCD_FORKED) { + if (exit_code == EXIT_SUCCESS) + logdebugx("forked to background"); + else + logerrx("exited with code %d", exit_code); + eloop_exit(ctx->eloop, exit_code); + } else + dhcpcd_signal_cb(exit_code, ctx); +} + static void dhcpcd_pidfile_timeout(void *arg) { -- 2.47.2