]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
dhcpcd: Close fork_fd on hangup
authorRoy Marples <roy@marples.name>
Wed, 8 Nov 2023 11:09:52 +0000 (11:09 +0000)
committerRoy Marples <roy@marples.name>
Fri, 10 Nov 2023 11:04:22 +0000 (11:04 +0000)
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

index 71e7d807d01bddca8b83dd05396986bce6749439..46c64b42f0601e220594406840a7754bfc41bfef 100644 (file)
@@ -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)
 {