diff options
| author | Richard Weinberger <richard@nod.at> | 2013-08-18 07:30:08 -0400 |
|---|---|---|
| committer | Richard Weinberger <richard@nod.at> | 2013-09-07 04:56:58 -0400 |
| commit | 91d44ff860a9e9c0db81a89cbc24fa31fbd8e6d3 (patch) | |
| tree | bb14601ab3afbcec3cb8d7d0f207d09cfc792268 | |
| parent | bc1d72e73be63a7c4a07eb10cf51e91f20bf6076 (diff) | |
um: Cleanup SIGTERM handling
Richard reported that some UML processes survive if the UML
main process receives a SIGTERM.
This issue was caused by a wrongly placed signal(SIGTERM, SIG_DFL)
in init_new_thread_signals().
It disabled the UML exit handler accidently for some processes.
The correct solution is to disable the fatal handler for all
UML helper threads/processes.
Such that last_ditch_exit() does not get called multiple times
and all processes can exit due to SIGTERM.
Reported-and-tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
| -rw-r--r-- | arch/um/drivers/ubd.h | 1 | ||||
| -rw-r--r-- | arch/um/drivers/ubd_kern.c | 3 | ||||
| -rw-r--r-- | arch/um/drivers/ubd_user.c | 5 | ||||
| -rw-r--r-- | arch/um/include/shared/os.h | 1 | ||||
| -rw-r--r-- | arch/um/os-Linux/aio.c | 5 | ||||
| -rw-r--r-- | arch/um/os-Linux/process.c | 1 | ||||
| -rw-r--r-- | arch/um/os-Linux/sigio.c | 2 | ||||
| -rw-r--r-- | arch/um/os-Linux/util.c | 10 |
8 files changed, 16 insertions, 12 deletions
diff --git a/arch/um/drivers/ubd.h b/arch/um/drivers/ubd.h index 3845051f1b10..3b48cd2081ee 100644 --- a/arch/um/drivers/ubd.h +++ b/arch/um/drivers/ubd.h | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #ifndef __UM_UBD_USER_H | 7 | #ifndef __UM_UBD_USER_H |
| 8 | #define __UM_UBD_USER_H | 8 | #define __UM_UBD_USER_H |
| 9 | 9 | ||
| 10 | extern void ignore_sigwinch_sig(void); | ||
| 11 | extern int start_io_thread(unsigned long sp, int *fds_out); | 10 | extern int start_io_thread(unsigned long sp, int *fds_out); |
| 12 | extern int io_thread(void *arg); | 11 | extern int io_thread(void *arg); |
| 13 | extern int kernel_fd; | 12 | extern int kernel_fd; |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 1812bc81715b..3716e6952554 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
| @@ -1476,7 +1476,8 @@ int io_thread(void *arg) | |||
| 1476 | struct io_thread_req *req; | 1476 | struct io_thread_req *req; |
| 1477 | int n; | 1477 | int n; |
| 1478 | 1478 | ||
| 1479 | ignore_sigwinch_sig(); | 1479 | os_fix_helper_signals(); |
| 1480 | |||
| 1480 | while(1){ | 1481 | while(1){ |
| 1481 | n = os_read_file(kernel_fd, &req, | 1482 | n = os_read_file(kernel_fd, &req, |
| 1482 | sizeof(struct io_thread_req *)); | 1483 | sizeof(struct io_thread_req *)); |
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index a703e45d8aac..e376f9b9c68d 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c | |||
| @@ -21,11 +21,6 @@ | |||
| 21 | #include "ubd.h" | 21 | #include "ubd.h" |
| 22 | #include <os.h> | 22 | #include <os.h> |
| 23 | 23 | ||
| 24 | void ignore_sigwinch_sig(void) | ||
| 25 | { | ||
| 26 | signal(SIGWINCH, SIG_IGN); | ||
| 27 | } | ||
| 28 | |||
| 29 | int start_io_thread(unsigned long sp, int *fd_out) | 24 | int start_io_thread(unsigned long sp, int *fd_out) |
| 30 | { | 25 | { |
| 31 | int pid, fds[2], err; | 26 | int pid, fds[2], err; |
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index e98303925cc5..021104d98cb3 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h | |||
| @@ -235,6 +235,7 @@ extern void setup_machinename(char *machine_out); | |||
| 235 | extern void setup_hostinfo(char *buf, int len); | 235 | extern void setup_hostinfo(char *buf, int len); |
| 236 | extern void os_dump_core(void) __attribute__ ((noreturn)); | 236 | extern void os_dump_core(void) __attribute__ ((noreturn)); |
| 237 | extern void um_early_printk(const char *s, unsigned int n); | 237 | extern void um_early_printk(const char *s, unsigned int n); |
| 238 | extern void os_fix_helper_signals(void); | ||
| 238 | 239 | ||
| 239 | /* time.c */ | 240 | /* time.c */ |
| 240 | extern void idle_sleep(unsigned long long nsecs); | 241 | extern void idle_sleep(unsigned long long nsecs); |
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 3a6bc2af0961..014eb35fd13b 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c | |||
| @@ -104,8 +104,7 @@ static int aio_thread(void *arg) | |||
| 104 | struct io_event event; | 104 | struct io_event event; |
| 105 | int err, n, reply_fd; | 105 | int err, n, reply_fd; |
| 106 | 106 | ||
| 107 | signal(SIGWINCH, SIG_IGN); | 107 | os_fix_helper_signals(); |
| 108 | |||
| 109 | while (1) { | 108 | while (1) { |
| 110 | n = io_getevents(ctx, 1, 1, &event, NULL); | 109 | n = io_getevents(ctx, 1, 1, &event, NULL); |
| 111 | if (n < 0) { | 110 | if (n < 0) { |
| @@ -173,7 +172,7 @@ static int not_aio_thread(void *arg) | |||
| 173 | struct aio_thread_reply reply; | 172 | struct aio_thread_reply reply; |
| 174 | int err; | 173 | int err; |
| 175 | 174 | ||
| 176 | signal(SIGWINCH, SIG_IGN); | 175 | os_fix_helper_signals(); |
| 177 | while (1) { | 176 | while (1) { |
| 178 | err = read(aio_req_fd_r, &req, sizeof(req)); | 177 | err = read(aio_req_fd_r, &req, sizeof(req)); |
| 179 | if (err != sizeof(req)) { | 178 | if (err != sizeof(req)) { |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 67b9c8f5a89e..33496fe2bb52 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
| @@ -294,5 +294,4 @@ void init_new_thread_signals(void) | |||
| 294 | signal(SIGHUP, SIG_IGN); | 294 | signal(SIGHUP, SIG_IGN); |
| 295 | set_handler(SIGIO); | 295 | set_handler(SIGIO); |
| 296 | signal(SIGWINCH, SIG_IGN); | 296 | signal(SIGWINCH, SIG_IGN); |
| 297 | signal(SIGTERM, SIG_DFL); | ||
| 298 | } | 297 | } |
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 8b61cc0e82c8..46e762f926eb 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c | |||
| @@ -55,7 +55,7 @@ static int write_sigio_thread(void *unused) | |||
| 55 | int i, n, respond_fd; | 55 | int i, n, respond_fd; |
| 56 | char c; | 56 | char c; |
| 57 | 57 | ||
| 58 | signal(SIGWINCH, SIG_IGN); | 58 | os_fix_helper_signals(); |
| 59 | fds = ¤t_poll; | 59 | fds = ¤t_poll; |
| 60 | while (1) { | 60 | while (1) { |
| 61 | n = poll(fds->poll, fds->used, -1); | 61 | n = poll(fds->poll, fds->used, -1); |
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 492ef5e6e166..faee55ef6d2f 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c | |||
| @@ -94,6 +94,16 @@ static inline void __attribute__ ((noreturn)) uml_abort(void) | |||
| 94 | exit(127); | 94 | exit(127); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | /* | ||
| 98 | * UML helper threads must not handle SIGWINCH/INT/TERM | ||
| 99 | */ | ||
| 100 | void os_fix_helper_signals(void) | ||
| 101 | { | ||
| 102 | signal(SIGWINCH, SIG_IGN); | ||
| 103 | signal(SIGINT, SIG_DFL); | ||
| 104 | signal(SIGTERM, SIG_DFL); | ||
| 105 | } | ||
| 106 | |||
| 97 | void os_dump_core(void) | 107 | void os_dump_core(void) |
| 98 | { | 108 | { |
| 99 | int pid; | 109 | int pid; |
