From: Alexander Paramonov <widgetcart...@gmail.com> Signed-off-by: Alexander Paramonov <widgetcart...@gmail.com> Signed-off-by: Laurent Vivier <laur...@vivier.eu> --- linux-user/qemu.h | 1 + linux-user/signal.c | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 627c8b3..ae87149 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -87,6 +87,7 @@ struct vm86_saved_state { struct sigqueue { struct sigqueue *next; target_siginfo_t info; + pid_t pid; }; struct emulated_sigtable { diff --git a/linux-user/signal.c b/linux-user/signal.c index 07ad07a..0ba11bd 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -472,6 +472,7 @@ int queue_signal(CPUState *env, int sig, target_siginfo_t *info) *pq = q; q->info = *info; q->next = NULL; + q->pid = getpid(); k->pending = 1; /* signal that a new signal is pending */ ts->signal_pending = 1; @@ -5231,21 +5232,34 @@ void process_pending_signals(CPUState *cpu_env) target_sigset_t target_old_set; struct emulated_sigtable *k; struct target_sigaction *sa; - struct sigqueue *q; - TaskState *ts = cpu_env->opaque; + struct sigqueue *q, *q_prev; + TaskState *ts = thread_env->opaque; if (!ts->signal_pending) return; - /* FIXME: This is not threadsafe. */ k = ts->sigtab; + int signal_pending = 0; for(sig = 1; sig <= TARGET_NSIG; sig++) { if (k->pending) - goto handle_signal; + { + q = k->first; + q_prev = NULL; + while (q) + { + if (q->pid == getpid()) + goto handle_signal; + else + signal_pending = 1; + q_prev = q; + q = q->next; + } + } k++; } + /* if no signal is pending, just return */ - ts->signal_pending = 0; + ts->signal_pending = signal_pending; return; handle_signal: @@ -5253,9 +5267,18 @@ void process_pending_signals(CPUState *cpu_env) fprintf(stderr, "qemu: process signal %d\n", sig); #endif /* dequeue signal */ - q = k->first; - k->first = q->next; - if (!k->first) + if (q_prev == k->first) + { + q = k->first; + k->first = q->next; + if (!k->first) + { + k->pending = 0; + } + } + else if (q_prev) + q_prev->next = q->next; + else k->pending = 0; sig = gdb_handlesig (cpu_env, sig); -- 1.7.2.3