aboutsummaryrefslogtreecommitdiff
path: root/linux-user/signal.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 17:15:59 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 17:15:59 +0000
commit773b93ee0684a9b9d1f0029a936a251411289027 (patch)
treed9e855fc9c0117e108445289665f3d74aa85ca24 /linux-user/signal.c
parent82c7e2a4c6745ace4dbf3f0792d98dcb08979c00 (diff)
signal fix: update the host signal 'signal ignored' state to avoid unexpected -EINTR values (ash fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@503 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/signal.c')
-rw-r--r--linux-user/signal.c52
1 files changed, 23 insertions, 29 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 587792d483..bb006cc79e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -370,33 +370,6 @@ int queue_signal(int sig, target_siginfo_t *info)
}
}
-#if defined(DEBUG_SIGNAL)
-#ifdef __i386__
-static void dump_regs(struct ucontext *uc)
-{
- fprintf(stderr,
- "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
- "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
- "EFL=%08x EIP=%08x\n",
- uc->uc_mcontext.gregs[EAX],
- uc->uc_mcontext.gregs[EBX],
- uc->uc_mcontext.gregs[ECX],
- uc->uc_mcontext.gregs[EDX],
- uc->uc_mcontext.gregs[ESI],
- uc->uc_mcontext.gregs[EDI],
- uc->uc_mcontext.gregs[EBP],
- uc->uc_mcontext.gregs[ESP],
- uc->uc_mcontext.gregs[EFL],
- uc->uc_mcontext.gregs[EIP]);
-}
-#else
-static void dump_regs(struct ucontext *uc)
-{
-}
-#endif
-
-#endif
-
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
@@ -416,7 +389,6 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
return;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "qemu: got signal %d\n", sig);
- dump_regs(puc);
#endif
host_to_target_siginfo_noswap(&tinfo, info);
if (queue_signal(sig, &tinfo) == 1) {
@@ -429,11 +401,13 @@ int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact)
{
struct emulated_sigaction *k;
+ struct sigaction act1;
+ int host_sig;
if (sig < 1 || sig > TARGET_NSIG)
return -EINVAL;
k = &sigact_table[sig - 1];
-#if defined(DEBUG_SIGNAL) && 0
+#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n",
sig, (int)act, (int)oact);
#endif
@@ -448,6 +422,26 @@ int do_sigaction(int sig, const struct target_sigaction *act,
k->sa.sa_flags = tswapl(act->sa_flags);
k->sa.sa_restorer = tswapl(act->sa_restorer);
k->sa.sa_mask = act->sa_mask;
+
+ /* we update the host linux signal state */
+ host_sig = target_to_host_signal(sig);
+ if (host_sig != SIGSEGV && host_sig != SIGBUS) {
+ sigfillset(&act1.sa_mask);
+ act1.sa_flags = SA_SIGINFO;
+ if (k->sa.sa_flags & TARGET_SA_RESTART)
+ act1.sa_flags |= SA_RESTART;
+ /* NOTE: it is important to update the host kernel signal
+ ignore state to avoid getting unexpected interrupted
+ syscalls */
+ if (k->sa._sa_handler == TARGET_SIG_IGN) {
+ act1.sa_sigaction = (void *)SIG_IGN;
+ } else if (k->sa._sa_handler == TARGET_SIG_DFL) {
+ act1.sa_sigaction = (void *)SIG_DFL;
+ } else {
+ act1.sa_sigaction = host_signal_handler;
+ }
+ sigaction(host_sig, &act1, NULL);
+ }
}
return 0;
}