Commit 603e4fd7b1e034f79181a53df9719818f80ba364
1 parent
3b3f24ad
linux-user: proper exit code for uncaught signals
The proper exit code for dieing from an uncaught signal is -<signal>. The kernel doesn't allow exit() or _exit() to pass a negative value. To get the proper exit code we need to actually die from an uncaught signal. A default signal handler is installed, we send ourself a signal and we wait for it to arrive. Patch originates from Scratchbox Signed-off-by: Riku Voipio <riku.voipio@iki.fi> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7119 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
25 additions
and
12 deletions
linux-user/signal.c
@@ -25,6 +25,7 @@ | @@ -25,6 +25,7 @@ | ||
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | #include <signal.h> | 26 | #include <signal.h> |
27 | #include <errno.h> | 27 | #include <errno.h> |
28 | +#include <assert.h> | ||
28 | #include <sys/ucontext.h> | 29 | #include <sys/ucontext.h> |
29 | 30 | ||
30 | #include "qemu.h" | 31 | #include "qemu.h" |
@@ -352,22 +353,34 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q) | @@ -352,22 +353,34 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q) | ||
352 | static void QEMU_NORETURN force_sig(int sig) | 353 | static void QEMU_NORETURN force_sig(int sig) |
353 | { | 354 | { |
354 | int host_sig; | 355 | int host_sig; |
356 | + struct sigaction act; | ||
355 | host_sig = target_to_host_signal(sig); | 357 | host_sig = target_to_host_signal(sig); |
356 | fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", | 358 | fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", |
357 | sig, strsignal(host_sig)); | 359 | sig, strsignal(host_sig)); |
358 | -#if 1 | ||
359 | gdb_signalled(thread_env, sig); | 360 | gdb_signalled(thread_env, sig); |
360 | - _exit(-host_sig); | ||
361 | -#else | ||
362 | - { | ||
363 | - struct sigaction act; | ||
364 | - sigemptyset(&act.sa_mask); | ||
365 | - act.sa_flags = SA_SIGINFO; | ||
366 | - act.sa_sigaction = SIG_DFL; | ||
367 | - sigaction(SIGABRT, &act, NULL); | ||
368 | - abort(); | ||
369 | - } | ||
370 | -#endif | 361 | + |
362 | + /* The proper exit code for dieing from an uncaught signal is | ||
363 | + * -<signal>. The kernel doesn't allow exit() or _exit() to pass | ||
364 | + * a negative value. To get the proper exit code we need to | ||
365 | + * actually die from an uncaught signal. Here the default signal | ||
366 | + * handler is installed, we send ourself a signal and we wait for | ||
367 | + * it to arrive. */ | ||
368 | + sigfillset(&act.sa_mask); | ||
369 | + act.sa_handler = SIG_DFL; | ||
370 | + sigaction(host_sig, &act, NULL); | ||
371 | + | ||
372 | + /* For some reason raise(host_sig) doesn't send the signal when | ||
373 | + * statically linked on x86-64. */ | ||
374 | + kill(getpid(), host_sig); | ||
375 | + | ||
376 | + /* Make sure the signal isn't masked (just reuse the mask inside | ||
377 | + of act) */ | ||
378 | + sigdelset(&act.sa_mask, host_sig); | ||
379 | + sigsuspend(&act.sa_mask); | ||
380 | + | ||
381 | + /* unreachable */ | ||
382 | + assert(0); | ||
383 | + | ||
371 | } | 384 | } |
372 | 385 | ||
373 | /* queue a signal so that it will be send to the virtual CPU as soon | 386 | /* queue a signal so that it will be send to the virtual CPU as soon |