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 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
... ...