@@ -694,6 +694,33 @@ void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
}
/* abort execution with signal */
+static G_NORETURN
+void die_with_signal(int sig)
+{
+ struct sigaction act = {
+ .sa_handler = SIG_DFL,
+ };
+
+ /*
+ * The proper exit code for dying 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
+ * the signal and we wait for it to arrive.
+ */
+ sigfillset(&act.sa_mask);
+ sigaction(sig, &act, NULL);
+
+ kill(getpid(), sig);
+
+ /* Make sure the signal isn't masked (reusing the mask inside of act). */
+ sigdelset(&act.sa_mask, sig);
+ sigsuspend(&act.sa_mask);
+
+ /* unreachable */
+ abort();
+}
+
static G_NORETURN
void dump_core_and_abort(CPUArchState *cpu_env, int target_sig)
{
@@ -701,7 +728,6 @@ void dump_core_and_abort(CPUArchState *cpu_env, int target_sig)
CPUArchState *env = cpu->env_ptr;
TaskState *ts = (TaskState *)cpu->opaque;
int host_sig, core_dumped = 0;
- struct sigaction act;
host_sig = target_to_host_signal(target_sig);
trace_user_dump_core_and_abort(env, target_sig, host_sig);
@@ -725,29 +751,7 @@ void dump_core_and_abort(CPUArchState *cpu_env, int target_sig)
}
preexit_cleanup(cpu_env, 128 + target_sig);
-
- /* The proper exit code for dying 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;
- act.sa_flags = 0;
- 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 */
- abort();
+ die_with_signal(host_sig);
}
/* queue a signal so that it will be send to the virtual CPU as soon
Because we trap so many signals for use by the guest, we have to take extra steps to exit properly. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/signal.c | 52 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-)