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 | 25 | #include <unistd.h> |
26 | 26 | #include <signal.h> |
27 | 27 | #include <errno.h> |
28 | +#include <assert.h> | |
28 | 29 | #include <sys/ucontext.h> |
29 | 30 | |
30 | 31 | #include "qemu.h" |
... | ... | @@ -352,22 +353,34 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q) |
352 | 353 | static void QEMU_NORETURN force_sig(int sig) |
353 | 354 | { |
354 | 355 | int host_sig; |
356 | + struct sigaction act; | |
355 | 357 | host_sig = target_to_host_signal(sig); |
356 | 358 | fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", |
357 | 359 | sig, strsignal(host_sig)); |
358 | -#if 1 | |
359 | 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 | 386 | /* queue a signal so that it will be send to the virtual CPU as soon | ... | ... |