Commit 603e4fd7b1e034f79181a53df9719818f80ba364

Authored by aurel32
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