[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/5] linux-user: Add support for multiplexing larger
From: |
Aleksandar Markovic |
Subject: |
[Qemu-devel] [PATCH 4/5] linux-user: Add support for multiplexing larger target signals |
Date: |
Wed, 22 May 2019 20:46:24 +0200 |
From: Miloš Stojanović <address@hidden>
Add MUX_SIG as a multiplex signal number for all target signals which are
out of the host range. Add support for multiplexing in do_sigaction(),
process_pending_signals(), target_set_sigmask() and do_target_sigprocmask().
This patch solves the problem of unusable target signals which are out of
the host range. This is done by enabling the usage of one of the host
signals (MUX_SIG) as a multiplex for all the target signals that are out
of range. In order to have the target signal masks available
TRACK_TARGET_MASK is defined which enables the tracking of the target
signals masks.
The table of signal handlers already supports the whole range of target
signals. In the do_sigaction() function the signal number of signals which
are out of range are replaced by MUX_SIG which bypasses the error from the
host system and doesn't interfere with signal handling on the target.
Since the MUX_SIG is used as a multiplex, it must never be blocked on host,
so support for emulating the blocking of this signal is added. This is done
by only blocking MUX_SIG in the target mask and retrieving its status from
there when it's needed.
Signed-off-by: Miloš Stojanović <address@hidden>
Signed-off-by: Aleksandar Markovic <address@hidden>
---
linux-user/signal.c | 32 ++++++++++++++++++++++++++++++++
linux-user/syscall_defs.h | 20 ++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9a73bfa..601de3e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -291,6 +291,15 @@ int do_target_sigprocmask(int how, const target_sigset_t
*target_set,
}
if (oldset) {
*oldset = ts->signal_mask;
+#ifdef MUX_SIG
+ /*
+ * The emulation of MUX_SIG being blocked is done using the
+ * target_signal_mask, so the status of MUX_SIG is taken from there.
+ */
+ if (target_sigismember(&ts->target_signal_mask, MUX_SIG) == 1) {
+ sigaddset(oldset, MUX_SIG);
+ }
+#endif
}
if (target_set && set) {
@@ -331,6 +340,15 @@ int do_target_sigprocmask(int how, const target_sigset_t
*target_set,
target_sigdelset(&ts->target_signal_mask, SIGSTOP);
sigdelset(&ts->signal_mask, SIGKILL);
sigdelset(&ts->signal_mask, SIGSTOP);
+#ifdef MUX_SIG
+ /*
+ * Since MUX_SIG is used for all the target signals out of the host
+ * range it must never be blocked on host. The emulation of MUX_SIG
+ * being blocked is done using the target_signal_mask. The status
+ * of MUX_SIG is taken form the target_signal_mask.
+ */
+ sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
}
return 0;
}
@@ -355,6 +373,10 @@ void target_set_sigmask(const sigset_t *set,
ts->signal_mask = *set;
ts->target_signal_mask = *target_set;
+#ifdef MUX_SIG
+ /* MUX_SIG can't be blocked on host */
+ sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
}
#endif
#endif
@@ -929,6 +951,12 @@ int do_sigaction(int sig, const struct target_sigaction
*act,
/* we update the host linux signal state */
host_sig = target_to_host_signal(sig);
+#ifdef MUX_SIG
+ /* put the out of host range signal into the multiplex */
+ if (sig >= _NSIG && sig < TARGET_NSIG) {
+ host_sig = MUX_SIG;
+ }
+#endif
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
sigfillset(&act1.sa_mask);
act1.sa_flags = SA_SIGINFO;
@@ -1141,6 +1169,10 @@ void process_pending_signals(CPUArchState *cpu_env)
set = ts->signal_mask;
sigdelset(&set, SIGSEGV);
sigdelset(&set, SIGBUS);
+#ifdef MUX_SIG
+ /* MUX_SIG can't be blocked on host */
+ sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
sigprocmask(SIG_SETMASK, &set, 0);
}
ts->in_sigsuspend = 0;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 64edec2..0c72509 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -387,6 +387,26 @@ struct target_dirent64 {
#define TARGET_NSIG_BPW TARGET_ABI_BITS
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
+#if _NSIG <= TARGET_NSIG
+/*
+ * MUX_SIG is used as a multiplex signal number - signals that are
+ * out of the host range and in the target range are sent through it.
+ * It is defined as the maximal available real-time signal in order to
+ * comply with the rule that low-numbered signals have highest priority.
+ * (signals using it will have the same priority but it will be smaller
+ * than all the other real-time signals)
+ * SIGRMTAX is avoided so it doesn't interfere with the hack of reversing
+ * __SIGRTMIN and __SIGRTMAX in the host_to_target_signal_table.
+ */
+#define MUX_SIG (SIGRTMAX - 1)
+
+/*
+ * The target signal masks must be tracked since they are larger than
+ * the host signal masks.
+ */
+#define TRACK_TARGET_SIGMASK
+#endif
+
typedef struct {
abi_ulong sig[TARGET_NSIG_WORDS];
} target_sigset_t;
--
2.7.4
- [Qemu-devel] [PATCH 0/5] linux-user: Support signal passing for targets having more signals than host, Aleksandar Markovic, 2019/05/22
- [Qemu-devel] [PATCH 4/5] linux-user: Add support for multiplexing larger target signals,
Aleksandar Markovic <=
- [Qemu-devel] [PATCH 2/5] linux-user: Add support for tracking the target signal mask, Aleksandar Markovic, 2019/05/22
- [Qemu-devel] [PATCH 1/5] linux-user: Fix sigismember() check, Aleksandar Markovic, 2019/05/22
- [Qemu-devel] [PATCH 3/5] linux-user: Add functionality for tracking target signal mask, Aleksandar Markovic, 2019/05/22
- [Qemu-devel] [PATCH 5/5] linux-user: Add support for multiplexing signals in more syscalls, Aleksandar Markovic, 2019/05/22
- Re: [Qemu-devel] [PATCH 0/5] linux-user: Support signal passing for targets having more signals than host, Peter Maydell, 2019/05/23