diff options
Diffstat (limited to 'arch/um/os-Linux/util.c')
| -rw-r--r-- | arch/um/os-Linux/util.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 6ea77979531c..42827cafa6af 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <stdio.h> | 6 | #include <stdio.h> |
| 7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
| 8 | #include <unistd.h> | ||
| 8 | #include <errno.h> | 9 | #include <errno.h> |
| 9 | #include <signal.h> | 10 | #include <signal.h> |
| 10 | #include <string.h> | 11 | #include <string.h> |
| @@ -75,6 +76,26 @@ void setup_hostinfo(char *buf, int len) | |||
| 75 | host.release, host.version, host.machine); | 76 | host.release, host.version, host.machine); |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 79 | /* | ||
| 80 | * We cannot use glibc's abort(). It makes use of tgkill() which | ||
| 81 | * has no effect within UML's kernel threads. | ||
| 82 | * After that glibc would execute an invalid instruction to kill | ||
| 83 | * the calling process and UML crashes with SIGSEGV. | ||
| 84 | */ | ||
| 85 | static inline void __attribute__ ((noreturn)) uml_abort(void) | ||
| 86 | { | ||
| 87 | sigset_t sig; | ||
| 88 | |||
| 89 | fflush(NULL); | ||
| 90 | |||
| 91 | if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT)) | ||
| 92 | sigprocmask(SIG_UNBLOCK, &sig, 0); | ||
| 93 | |||
| 94 | for (;;) | ||
| 95 | if (kill(getpid(), SIGABRT) < 0) | ||
| 96 | exit(127); | ||
| 97 | } | ||
| 98 | |||
| 78 | void os_dump_core(void) | 99 | void os_dump_core(void) |
| 79 | { | 100 | { |
| 80 | int pid; | 101 | int pid; |
| @@ -116,5 +137,5 @@ void os_dump_core(void) | |||
| 116 | while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) | 137 | while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) |
| 117 | os_kill_ptraced_process(pid, 0); | 138 | os_kill_ptraced_process(pid, 0); |
| 118 | 139 | ||
| 119 | abort(); | 140 | uml_abort(); |
| 120 | } | 141 | } |
