um: Reap winch thread if it fails
authorBenjamin Berg <benjamin@sipsolutions.net>
Fri, 10 Nov 2023 11:03:43 +0000 (12:03 +0100)
committerRichard Weinberger <richard@nod.at>
Thu, 4 Jan 2024 22:51:23 +0000 (23:51 +0100)
When the winch thread runs into an error condition, it would exit(1) and
never be reaped until shutdown time. Change this to write a command byte
which causes the driver to kill it, therefore reaping the child.

Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
Signed-off-by: Richard Weinberger <richard@nod.at>
arch/um/drivers/chan_user.c
arch/um/drivers/line.c

index c2b83cb99aae0e931bdb4cad26f8be7cea396e2e..ed7cc830b3e7bc4100fa3ed4232c481aa54ddd78 100644 (file)
@@ -141,7 +141,7 @@ struct winch_data {
        int pipe_fd;
 };
 
-static int winch_thread(void *arg)
+static __noreturn int winch_thread(void *arg)
 {
        struct winch_data *data = arg;
        sigset_t sigs;
@@ -168,7 +168,7 @@ static int winch_thread(void *arg)
        if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0) {
                os_info("winch_thread : sigprocmask failed, errno = %d\n",
                        errno);
-               exit(1);
+               goto wait_kill;
        }
        /* In sigsuspend(), block anything else than SIGWINCH. */
        sigdelset(&sigs, SIGWINCH);
@@ -176,19 +176,19 @@ static int winch_thread(void *arg)
        if (setsid() < 0) {
                os_info("winch_thread : setsid failed, errno = %d\n",
                       errno);
-               exit(1);
+               goto wait_kill;
        }
 
        if (ioctl(pty_fd, TIOCSCTTY, 0) < 0) {
                os_info("winch_thread : TIOCSCTTY failed on "
                        "fd %d err = %d\n", pty_fd, errno);
-               exit(1);
+               goto wait_kill;
        }
 
        if (tcsetpgrp(pty_fd, os_getpid()) < 0) {
                os_info("winch_thread : tcsetpgrp failed on fd %d err = %d\n",
                        pty_fd, errno);
-               exit(1);
+               goto wait_kill;
        }
 
        /*
@@ -214,6 +214,12 @@ static int winch_thread(void *arg)
                        os_info("winch_thread : write failed, err = %d\n",
                                errno);
        }
+
+wait_kill:
+       c = 2;
+       count = write(pipe_fd, &c, sizeof(c));
+       while (1)
+               pause();
 }
 
 static int winch_tramp(int fd, struct tty_port *port, int *fd_out,
index b98545f3edb5033260dad9590d812f3ddc522360..449d320c3f553a6b5fa267dce4f04b8b81285996 100644 (file)
@@ -629,15 +629,18 @@ static irqreturn_t winch_interrupt(int irq, void *data)
 
        if (fd != -1) {
                err = generic_read(fd, &c, NULL);
-               if (err < 0) {
+               /* A read of 2 means the winch thread failed and has warned */
+               if (err < 0 || (err == 1 && c == 2)) {
                        if (err != -EAGAIN) {
                                winch->fd = -1;
                                list_del(&winch->list);
                                os_close_file(fd);
-                               printk(KERN_ERR "winch_interrupt : "
-                                      "read failed, errno = %d\n", -err);
-                               printk(KERN_ERR "fd %d is losing SIGWINCH "
-                                      "support\n", winch->tty_fd);
+                               if (err < 0) {
+                                       printk(KERN_ERR "winch_interrupt : read failed, errno = %d\n",
+                                              -err);
+                                       printk(KERN_ERR "fd %d is losing SIGWINCH support\n",
+                                              winch->tty_fd);
+                               }
                                INIT_WORK(&winch->work, __free_winch);
                                schedule_work(&winch->work);
                                return IRQ_HANDLED;