[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 25/30] bsd-user/signal.c: handle_pending_signal
|
From: |
Warner Losh |
|
Subject: |
[PATCH 25/30] bsd-user/signal.c: handle_pending_signal |
|
Date: |
Sun, 9 Jan 2022 09:19:18 -0700 |
Handle a queued signal.
Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Kyle Evans <kevans@freebsd.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
---
bsd-user/qemu.h | 2 +
bsd-user/signal.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+)
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index e8c417c7c33..011fdfebbaa 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -97,7 +97,9 @@ typedef struct TaskState {
struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
int signal_pending; /* non zero if a signal may be pending */
+ bool in_sigsuspend;
sigset_t signal_mask;
+ sigset_t sigsuspend_mask;
uint8_t stack[];
} __attribute__((aligned(16))) TaskState;
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index 8e1427553da..934528d5fb0 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -649,6 +649,102 @@ void signal_init(void)
}
}
+static void handle_pending_signal(CPUArchState *cpu_env, int sig,
+ struct emulated_sigtable *k)
+{
+ CPUState *cpu = env_cpu(cpu_env);
+ TaskState *ts = cpu->opaque;
+ struct qemu_sigqueue *q;
+ struct target_sigaction *sa;
+ int code;
+ sigset_t set;
+ abi_ulong handler;
+ target_siginfo_t tinfo;
+ target_sigset_t target_old_set;
+
+ trace_user_handle_signal(cpu_env, sig);
+
+ /* Dequeue signal. */
+ q = k->first;
+ k->first = q->next;
+ if (!k->first) {
+ k->pending = 0;
+ }
+
+ sig = gdb_handlesig(cpu, sig);
+ if (!sig) {
+ sa = NULL;
+ handler = TARGET_SIG_IGN;
+ } else {
+ sa = &sigact_table[sig - 1];
+ handler = sa->_sa_handler;
+ }
+
+ if (do_strace) {
+ print_taken_signal(sig, &q->info);
+ }
+
+ if (handler == TARGET_SIG_DFL) {
+ /*
+ * default handler : ignore some signal. The other are job
+ * control or fatal.
+ */
+ if (TARGET_SIGTSTP == sig || TARGET_SIGTTIN == sig ||
+ TARGET_SIGTTOU == sig) {
+ kill(getpid(), SIGSTOP);
+ } else if (TARGET_SIGCHLD != sig && TARGET_SIGURG != sig &&
+ TARGET_SIGINFO != sig &&
+ TARGET_SIGWINCH != sig && TARGET_SIGCONT != sig) {
+ force_sig(sig);
+ }
+ } else if (TARGET_SIG_IGN == handler) {
+ /* ignore sig */
+ } else if (TARGET_SIG_ERR == handler) {
+ force_sig(sig);
+ } else {
+ /* compute the blocked signals during the handler execution */
+ sigset_t *blocked_set;
+
+ target_to_host_sigset(&set, &sa->sa_mask);
+ /*
+ * SA_NODEFER indicates that the current signal should not be
+ * blocked during the handler.
+ */
+ if (!(sa->sa_flags & TARGET_SA_NODEFER)) {
+ sigaddset(&set, target_to_host_signal(sig));
+ }
+
+ /*
+ * Save the previous blocked signal state to restore it at the
+ * end of the signal execution (see do_sigreturn).
+ */
+ host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
+
+ blocked_set = ts->in_sigsuspend ?
+ &ts->sigsuspend_mask : &ts->signal_mask;
+ qemu_sigorset(&ts->signal_mask, blocked_set, &set);
+ ts->in_sigsuspend = false;
+ sigprocmask(SIG_SETMASK, &ts->signal_mask, NULL);
+
+ /* XXX VM86 on x86 ??? */
+
+ code = q->info.si_code;
+ /* prepare the stack frame of the virtual CPU */
+ if (sa->sa_flags & TARGET_SA_SIGINFO) {
+ tswap_siginfo(&tinfo, &q->info);
+ setup_frame(sig, code, sa, &target_old_set, &tinfo, cpu_env);
+ } else {
+ setup_frame(sig, code, sa, &target_old_set, NULL, cpu_env);
+ }
+ if (sa->sa_flags & TARGET_SA_RESETHAND) {
+ sa->_sa_handler = TARGET_SIG_DFL;
+ }
+ }
+ if (q != &k->info) {
+ free_sigqueue(cpu_env, q);
+ }
+}
+
void process_pending_signals(CPUArchState *cpu_env)
{
}
--
2.33.1
[PATCH 18/30] bsd-user/signal.c: Implement host_signal_handler, Warner Losh, 2022/01/09
[PATCH 19/30] bsd-user/strace.c: print_taken_signal, Warner Losh, 2022/01/09