]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
control: deal with hangup better
authorRoy Marples <roy@marples.name>
Wed, 17 May 2023 02:08:45 +0000 (03:08 +0100)
committerRoy Marples <roy@marples.name>
Wed, 17 May 2023 02:08:45 +0000 (03:08 +0100)
Maybe fix #205

src/control.c
src/privsep-control.c

index 0b7133e2314be2f95ffeebc174374343a3cda21c..ecd6d47febe1c2b8db6cee3362e777479a376ee3 100644 (file)
@@ -93,6 +93,19 @@ control_free(struct fd_list *fd)
        free(fd);
 }
 
+static void
+control_hangup(struct fd_list *fd)
+{
+
+#ifdef PRIVSEP
+       if (IN_PRIVSEP(fd->ctx)) {
+               if (ps_ctl_sendeof(fd) == -1)
+                       logerr(__func__);
+       }
+#endif
+       control_free(fd);
+}
+
 static void
 control_handle_read(struct fd_list *fd)
 {
@@ -100,16 +113,9 @@ control_handle_read(struct fd_list *fd)
        ssize_t bytes;
 
        bytes = read(fd->fd, buffer, sizeof(buffer) - 1);
-       if (bytes == -1)
+       if (bytes == -1) {
                logerr(__func__);
-       if (bytes == -1 || bytes == 0) {
-#ifdef PRIVSEP
-               if (IN_PRIVSEP(fd->ctx)) {
-                       if (ps_ctl_sendeof(fd) == -1)
-                               logerr(__func__);
-               }
-#endif
-               control_free(fd);
+               control_hangup(fd);
                return;
        }
 
@@ -159,7 +165,7 @@ control_handle_write(struct fd_list *fd)
 
        if (writev(fd->fd, iov, iov_len) == -1) {
                logerr("%s: write", __func__);
-               control_free(fd);
+               control_hangup(fd);
                return;
        }
 
@@ -194,13 +200,15 @@ control_handle_data(void *arg, unsigned short events)
 {
        struct fd_list *fd = arg;
 
-       if (!(events & (ELE_READ | ELE_WRITE)))
+       if (!(events & (ELE_READ | ELE_WRITE | ELE_HANGUP)))
                logerrx("%s: unexpected event 0x%04x", __func__, events);
 
        if (events & ELE_WRITE && !(events & ELE_HANGUP))
                control_handle_write(fd);
        if (events & ELE_READ)
                control_handle_read(fd);
+       if (events & ELE_HANGUP)
+               control_hangup(fd);
 }
 
 void
index abea50240a2af8fc91bb337bd1b6c47a9abb8760..38f18c4ec163517f402b992211826d8073a68723 100644 (file)
@@ -64,27 +64,13 @@ ps_ctl_startcb(struct ps_process *psp)
            ctx->options & DHCPCD_MANAGER ? NULL : *ctx->ifv, af);
 }
 
-static ssize_t
-ps_ctl_recvmsgcb(void *arg, struct ps_msghdr *psm, __unused struct msghdr *msg)
-{
-       struct dhcpcd_ctx *ctx = arg;
-
-       if (psm->ps_cmd != PS_CTL_EOF) {
-               errno = ENOTSUP;
-               return -1;
-       }
-
-       ctx->ps_control_client = NULL;
-       return 0;
-}
-
 static void
 ps_ctl_recvmsg(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
 
        if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events,
-           ps_ctl_recvmsgcb, psp->psp_ctx) == -1)
+           NULL, psp->psp_ctx) == -1)
                logerr(__func__);
 }
 
@@ -175,22 +161,26 @@ ps_ctl_recv(void *arg, unsigned short events)
        char buf[BUFSIZ];
        ssize_t len;
 
-       if (!(events & ELE_READ))
+       if (!(events & (ELE_READ | ELE_HANGUP)))
                logerrx("%s: unexpected event 0x%04x", __func__, events);
 
-       len = read(ctx->ps_ctl->psp_work_fd, buf, sizeof(buf));
-       if (len == 0)
-               return;
-       if (len == -1) {
-               logerr("%s: read", __func__);
-               eloop_exit(ctx->eloop, EXIT_FAILURE);
-               return;
+       if (events & ELE_READ) {
+               len = read(ctx->ps_ctl->psp_work_fd, buf, sizeof(buf));
+               if (len == -1)
+                       logerr("%s: read", __func__);
+               else if (len == 0)
+                       // FIXME: Why does this happen?
+                       ;
+               else if (ctx->ps_control_client == NULL)
+                       logerrx("%s: clientfd #%d disconnected (len=%zd)",
+                           __func__, ctx->ps_ctl->psp_work_fd, len);
+               else {
+                       errno = 0;
+                       if (control_queue(ctx->ps_control_client,
+                           buf, (size_t)len) == -1)
+                               logerr("%s: control_queue", __func__);
+               }
        }
-       if (ctx->ps_control_client == NULL) /* client disconnected */
-               return;
-       errno = 0;
-       if (control_queue(ctx->ps_control_client, buf, (size_t)len) == -1)
-               logerr("%s: control_queue", __func__);
 }
 
 static void
@@ -205,8 +195,6 @@ ps_ctl_listen(void *arg, unsigned short events)
                logerrx("%s: unexpected event 0x%04x", __func__, events);
 
        len = read(ctx->ps_control->fd, buf, sizeof(buf));
-       if (len == 0)
-               return;
        if (len == -1) {
                logerr("%s: read", __func__);
                eloop_exit(ctx->eloop, EXIT_FAILURE);