summaryrefslogtreecommitdiff
path: root/arch/um
diff options
context:
space:
mode:
authorBenjamin Berg <benjamin@sipsolutions.net>2023-11-10 12:03:43 +0100
committerRichard Weinberger <richard@nod.at>2024-01-04 23:51:23 +0100
commit139e6e8ef6ee9a56fc1737240ecd8402fbcadd82 (patch)
tree76dd2aadcfe4fdd3892f9646e36714e2a0f2b407 /arch/um
parent1818b8406678a78b823dad44c91580f859403ced (diff)
um: Reap winch thread if it fails
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>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/chan_user.c16
-rw-r--r--arch/um/drivers/line.c13
2 files changed, 19 insertions, 10 deletions
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index c2b83cb99aae..ed7cc830b3e7 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -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,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index b98545f3edb5..449d320c3f55 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -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;