linux-user: Proper exit code for uncaught signals
PATCH 1/1 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
--- linux-user/signal.c | 37 +++++++++++++++++++++++++------------ 1 files changed, 25 insertions(+), 12 deletions(-)
linux-user/signal.c +25 -12
@@ -24,6 +24,7 @@#include <unistd.h> #include <signal.h> #include <errno.h> +#include <assert.h> #include <sys/ucontext.h> #include "qemu.h"
@@ -328,21 +329,33 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q)static void __attribute((noreturn))force_sig (int sig) {int host_sig; +struct sigaction act; host_sig =target_to_host_signal (sig);fprintf (stderr,"qemu: uncaught target signal %d (%s) - exiting\n" , sig,strsignal (host_sig)); -#if 1 -_exit (-host_sig); -#else - { -struct sigaction act; -sigemptyset (&act.sa_mask); - act.sa_flags =SA_SIGINFO ; - act.sa_sigaction =SIG_DFL ; -sigaction (SIGABRT , &act,NULL ); -abort (); - } -#endif + +/* 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. Here the default signal +* handler is installed, we send ourself a signal and we wait for +* it to arrive. */ +sigfillset (&act.sa_mask); + act.sa_handler =SIG_DFL ; +sigaction (host_sig, &act,NULL ); + +/* For some reason raise(host_sig) doesn't send the signal when +* statically linked on x86-64. */ +kill (getpid (), host_sig); + +/* Make sure the signal isn't masked (just reuse the mask inside +of act) */ +sigdelset (&act.sa_mask, host_sig); +sigsuspend (&act.sa_mask); + +/* unreachable */ +assert (0 ); + }/* queue a signal so that it will be send to the virtual CPU as soon
Signature · 5 lines
1.5.6.5 -- "rm -rf" only sounds scary if you don't have backups
Quoted 9 lines · Riku Voipio
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
So, who holds the copyright (and deserves the credit)?
Thiemo
Quoted 70 lines
Signed-off-by Riku Voipio <[email protected]>--- linux-user/signal.c | 37 +++++++++++++++++++++++++------------ 1 files changed, 25 insertions(+), 12 deletions(-)linux-user/signal.c +25
-12@@ -24,6 +24,7 @@#include <unistd.h> #include <signal.h> #include <errno.h> +#include <assert.h> #include <sys/ucontext.h> #include "qemu.h" @@ -328,21 +329,33 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q)static void __attribute((noreturn))force_sig (int sig) {int host_sig; +struct sigaction act; host_sig =target_to_host_signal (sig);fprintf (stderr,"qemu: uncaught target signal %d (%s) - exiting\n" , sig,strsignal (host_sig)); -#if 1 -_exit (-host_sig); -#else - { -struct sigaction act; -sigemptyset (&act.sa_mask); - act.sa_flags =SA_SIGINFO ; - act.sa_sigaction =SIG_DFL ; -sigaction (SIGABRT , &act,NULL ); -abort (); - } -#endif + +/* 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. Here the default signal +* handler is installed, we send ourself a signal and we wait for +* it to arrive. */ +sigfillset (&act.sa_mask); + act.sa_handler =SIG_DFL ; +sigaction (host_sig, &act,NULL ); + +/* For some reason raise(host_sig) doesn't send the signal when +* statically linked on x86-64. */ +kill (getpid (), host_sig); + +/* Make sure the signal isn't masked (just reuse the mask inside +of act) */ +sigdelset (&act.sa_mask, host_sig); +sigsuspend (&act.sa_mask); + +/* unreachable */ +assert (0 ); + }/* queue a signal so that it will be send to the virtual CPU as soon Signature · 5 lines
1.5.6.5 -- "rm -rf" only sounds scary if you don't have backups
Quoted 4 lines
Quoted 4 lines
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.
It's nothing like -<signal>, so the comment should be changed.
The general principle of sending yourself a signal to get the right exit status is good.
Quoted 3 lines
linux-user/signal.c static inline void free_sigqueue(CPUState *env, struct sigqueue *q) · line 345
Quoted 3 lines
linux-user/signal.c +3
-0+sigfillset (&act.sa_mask); + act.sa_handler =SIG_DFL ; +sigaction (host_sig, &act,NULL );
What if the SIG_DFL _host_ behaviour is not to terminate the host process, but it has terminated the guest process? Awkward one.
Quoted 3 lines
linux-user/signal.c static inline void free_sigqueue(CPUState *env, struct sigqueue *q) · line 349
Quoted 3 lines
linux-user/signal.c +3
-0+/* For some reason raise(host_sig) doesn't send the signal when +* statically linked on x86-64. */ +kill (getpid (), host_sig);
Is getpid() always right here, and should tgkill() or tkill() be used when clone is supported?
-- Jamie
Quoted 6 lines · Jamie Lokier
Quoted 4 lines
Quoted 4 lines
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.It's nothing like -<signal>, so the comment should be changed.
Something like:
Proper exit code for dieing from an uncaught signal differs from normal exit, so applications using WISIGNALED/WTERMSIG don't get the expected result. The proper way is to actually die from an uncaught signal.
Quoted 9 lines
The general principle of sending yourself a signal to get the right exit status is good.
Quoted 3 lines
linux-user/signal.c static inline void free_sigqueue(CPUState *env, struct sigqueue *q) · line 345
Quoted 3 lines
linux-user/signal.c +3
-0+sigfillset (&act.sa_mask); + act.sa_handler =SIG_DFL ; +sigaction (host_sig, &act,NULL );What if the
SIG_DFL_host_ behaviour is not to terminate the host process, but it has terminated the guest process? Awkward one.
Could this happen on Linux or is this a portability issue?
Quoted 6 lines
Quoted 3 lines
linux-user/signal.c static inline void free_sigqueue(CPUState *env, struct sigqueue *q) · line 349
Quoted 3 lines
linux-user/signal.c +3
-0+/* For some reason raise(host_sig) doesn't send the signal when +* statically linked on x86-64. */ +kill (getpid (), host_sig);Is
getpid()always right here, and shouldtgkill()ortkill()be used when clone is supported?
I'll have to look into this. The thought that this code needs to do multithreaded signal handling (preferredly in a portable fashion) feels like I'm heading towards endless swamplands..
Signature · 1 line
"rm -rf" only sounds scary if you don't have backups
Quoted 6 lines · Thiemo Seufer
Quoted 5 lines · Riku Voipio
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.
Quoted 6 lines
Quoted 4 lines
A default signal handler is installed, we send ourself a signal and we wait for it to arrive.
Patch originates from Scratchbox
So, who holds the copyright (and deserves the credit)?
The qemu tarball[1] provided on scratchbox site doesn't document who wrote patches and who has the copyright. Most likely a contractor for Nokia wrote it, and the copyright is Nokia's.
Lauro might know as the patch is also at the qemu-arm-eabi sf project site.
Quoted 72 lines
Thiemo
Quoted 70 lines
Signed-off-by Riku Voipio <[email protected]>--- linux-user/signal.c | 37 +++++++++++++++++++++++++------------ 1 files changed, 25 insertions(+), 12 deletions(-)linux-user/signal.c +25
-12@@ -24,6 +24,7 @@#include <unistd.h> #include <signal.h> #include <errno.h> +#include <assert.h> #include <sys/ucontext.h> #include "qemu.h" @@ -328,21 +329,33 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q)static void __attribute((noreturn))force_sig (int sig) {int host_sig; +struct sigaction act; host_sig =target_to_host_signal (sig);fprintf (stderr,"qemu: uncaught target signal %d (%s) - exiting\n" , sig,strsignal (host_sig)); -#if 1 -_exit (-host_sig); -#else - { -struct sigaction act; -sigemptyset (&act.sa_mask); - act.sa_flags =SA_SIGINFO ; - act.sa_sigaction =SIG_DFL ; -sigaction (SIGABRT , &act,NULL ); -abort (); - } -#endif + +/* 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. Here the default signal +* handler is installed, we send ourself a signal and we wait for +* it to arrive. */ +sigfillset (&act.sa_mask); + act.sa_handler =SIG_DFL ; +sigaction (host_sig, &act,NULL ); + +/* For some reason raise(host_sig) doesn't send the signal when +* statically linked on x86-64. */ +kill (getpid (), host_sig); + +/* Make sure the signal isn't masked (just reuse the mask inside +of act) */ +sigdelset (&act.sa_mask, host_sig); +sigsuspend (&act.sa_mask); + +/* unreachable */ +assert (0 ); + }/* queue a signal so that it will be send to the virtual CPU as soon Signature · 5 lines
1.5.6.5 -- "rm -rf" only sounds scary if you don't have backups
Signature · 1 line
"rm -rf" only sounds scary if you don't have backups