From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:46753) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qtn2E-0004bn-Ss for qemu-devel@nongnu.org; Wed, 17 Aug 2011 16:48:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qtn2D-0006c7-4Z for qemu-devel@nongnu.org; Wed, 17 Aug 2011 16:48:22 -0400 Received: from mail-yi0-f45.google.com ([209.85.218.45]:33471) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qtn2D-0006bk-1y for qemu-devel@nongnu.org; Wed, 17 Aug 2011 16:48:21 -0400 Received: by yih10 with SMTP id 10so1231438yih.4 for ; Wed, 17 Aug 2011 13:48:19 -0700 (PDT) From: Bryce Lanham Date: Wed, 17 Aug 2011 15:46:06 -0500 Message-Id: <1313614076-28878-2-git-send-email-blanham@gmail.com> In-Reply-To: <1313614076-28878-1-git-send-email-blanham@gmail.com> References: <1313614076-28878-1-git-send-email-blanham@gmail.com> Subject: [Qemu-devel] [PATCH 001/111] linux-user: Signals processing is not thread-safe. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Laurent Vivier , Alexander Paramonov From: Alexander Paramonov Signed-off-by: Alexander Paramonov Signed-off-by: Laurent Vivier --- 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