mirror of https://github.com/xemu-project/xemu.git
bsd-user/signal.c: process_pending_signals
Process the currently queued signals. Signed-off-by: Stacey Son <sson@FreeBSD.org> Signed-off-by: Kyle Evans <kevans@freebsd.org> Signed-off-by: Warner Losh <imp@bsdimp.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
08eb66d5d8
commit
d7acd31780
|
@ -756,8 +756,62 @@ static void handle_pending_signal(CPUArchState *env, int sig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_pending_signals(CPUArchState *cpu_env)
|
void process_pending_signals(CPUArchState *env)
|
||||||
{
|
{
|
||||||
|
CPUState *cpu = env_cpu(env);
|
||||||
|
int sig;
|
||||||
|
sigset_t *blocked_set, set;
|
||||||
|
struct emulated_sigtable *k;
|
||||||
|
TaskState *ts = cpu->opaque;
|
||||||
|
|
||||||
|
while (qatomic_read(&ts->signal_pending)) {
|
||||||
|
sigfillset(&set);
|
||||||
|
sigprocmask(SIG_SETMASK, &set, 0);
|
||||||
|
|
||||||
|
restart_scan:
|
||||||
|
sig = ts->sync_signal.pending;
|
||||||
|
if (sig) {
|
||||||
|
/*
|
||||||
|
* Synchronous signals are forced by the emulated CPU in some way.
|
||||||
|
* If they are set to ignore, restore the default handler (see
|
||||||
|
* sys/kern_sig.c trapsignal() and execsigs() for this behavior)
|
||||||
|
* though maybe this is done only when forcing exit for non SIGCHLD.
|
||||||
|
*/
|
||||||
|
if (sigismember(&ts->signal_mask, target_to_host_signal(sig)) ||
|
||||||
|
sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
|
||||||
|
sigdelset(&ts->signal_mask, target_to_host_signal(sig));
|
||||||
|
sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
|
||||||
|
}
|
||||||
|
handle_pending_signal(env, sig, &ts->sync_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
k = ts->sigtab;
|
||||||
|
for (sig = 1; sig <= TARGET_NSIG; sig++, k++) {
|
||||||
|
blocked_set = ts->in_sigsuspend ?
|
||||||
|
&ts->sigsuspend_mask : &ts->signal_mask;
|
||||||
|
if (k->pending &&
|
||||||
|
!sigismember(blocked_set, target_to_host_signal(sig))) {
|
||||||
|
handle_pending_signal(env, sig, k);
|
||||||
|
/*
|
||||||
|
* Restart scan from the beginning, as handle_pending_signal
|
||||||
|
* might have resulted in a new synchronous signal (eg SIGSEGV).
|
||||||
|
*/
|
||||||
|
goto restart_scan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unblock signals and check one more time. Unblocking signals may cause
|
||||||
|
* us to take another host signal, which will set signal_pending again.
|
||||||
|
*/
|
||||||
|
qatomic_set(&ts->signal_pending, 0);
|
||||||
|
ts->in_sigsuspend = false;
|
||||||
|
set = ts->signal_mask;
|
||||||
|
sigdelset(&set, SIGSEGV);
|
||||||
|
sigdelset(&set, SIGBUS);
|
||||||
|
sigprocmask(SIG_SETMASK, &set, 0);
|
||||||
|
}
|
||||||
|
ts->in_sigsuspend = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr,
|
void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr,
|
||||||
|
|
Loading…
Reference in New Issue