From patchwork Fri Dec 26 20:31:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 4426 Received: (qmail 30543 invoked by alias); 26 Dec 2014 20:31:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 30504 invoked by uid 89); 26 Dec 2014 20:31:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 26 Dec 2014 20:31:35 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sBQKVXSx029714 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Fri, 26 Dec 2014 15:31:33 -0500 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sBQKVG2o011395 for ; Fri, 26 Dec 2014 15:31:30 -0500 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 1/8] gdb.threads/{siginfo-thread.c, watchthreads-reorder.c, ia64-sigill.c} races with GDB Date: Fri, 26 Dec 2014 20:31:04 +0000 Message-Id: <1419625871-28848-2-git-send-email-palves@redhat.com> In-Reply-To: <1419625871-28848-1-git-send-email-palves@redhat.com> References: <1419625871-28848-1-git-send-email-palves@redhat.com> These three test all spawn a few threads and then send a SIGSTOP to their parent GDB in order to pause it while the new threads set things up for the test. With a GDB patch that changes the inferior thread's scheduling a bit, I sometimes see: FAIL: gdb.threads/siginfo-threads.exp: catch signal 0 (timeout) ... FAIL: gdb.threads/watchthreads-reorder.exp: reorder1: continue a (timeout) ... FAIL: gdb.threads/ia64-sigill.exp: continue (timeout) ... The issue is that the test program stops GDB before it had a chance of processing the new thread's clone event: (gdb) PASS: gdb.threads/siginfo-threads.exp: get pid continue Continuing. Stopping GDB PID 21541. Waiting till the threads initialize their TIDs. FAIL: gdb.threads/siginfo-threads.exp: catch signal 0 (timeout) On Linux (at least), new threads start stopped, and the debugger must resume them. The fix is to make the test program wait for the new threads to be running before stopping GDB. gdb/testsuite/ 2014-12-26 Pedro Alves * gdb.threads/ia64-sigill.c (threads_started_barrier): New global. (thread_func): Wait on barrier. (main): Wait for all threads to start before stopping GDB. * gdb.threads/siginfo-threads.c (threads_started_barrier): New global. (thread1_func, thread2_func): Wait on barrier. (main): Wait for all threads to start before stopping GDB. * gdb.threads/watchthreads-reorder.c (threads_started_barrier): New global. (thread1_func, thread2_func): Wait on barrier. (main): Wait for all threads to start before stopping GDB. --- gdb/testsuite/gdb.threads/ia64-sigill.c | 11 +++++++++++ gdb/testsuite/gdb.threads/siginfo-threads.c | 13 +++++++++++++ gdb/testsuite/gdb.threads/watchthreads-reorder.c | 13 +++++++++++++ 3 files changed, 37 insertions(+) diff --git a/gdb/testsuite/gdb.threads/ia64-sigill.c b/gdb/testsuite/gdb.threads/ia64-sigill.c index 4833e47..a685fb0 100644 --- a/gdb/testsuite/gdb.threads/ia64-sigill.c +++ b/gdb/testsuite/gdb.threads/ia64-sigill.c @@ -44,6 +44,8 @@ static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_ static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; +static pthread_barrier_t threads_started_barrier; + /* Do not use alarm as it would create a ptrace event which would hang up us if we are being traced by GDB which we stopped ourselves. */ @@ -78,6 +80,8 @@ thread_func (void *threadno_voidp) int threadno = (intptr_t) threadno_voidp; int i; + pthread_barrier_wait (&threads_started_barrier); + switch (threadno) { case 1: @@ -272,6 +276,8 @@ main (int argc, char **argv) timed_mutex_lock (&terminate_mutex); + pthread_barrier_init (&threads_started_barrier, NULL, 3); + i = pthread_create (&thread1, NULL, thread_func, (void *) (intptr_t) 1); assert (i == 0); @@ -298,6 +304,11 @@ main (int argc, char **argv) atexit (cleanup); + /* Wait until all threads are seen running. On Linux (at least), + new threads start stopped, and the debugger must resume them. + Need to wait for that before stopping GDB. */ + pthread_barrier_wait (&threads_started_barrier); + printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); if (tracer) diff --git a/gdb/testsuite/gdb.threads/siginfo-threads.c b/gdb/testsuite/gdb.threads/siginfo-threads.c index 7aa1ea2..b86df54 100644 --- a/gdb/testsuite/gdb.threads/siginfo-threads.c +++ b/gdb/testsuite/gdb.threads/siginfo-threads.c @@ -54,6 +54,8 @@ static int thread2_sigusr2_hit; static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; +static pthread_barrier_t threads_started_barrier; + /* Do not use alarm as it would create a ptrace event which would hang us up if we are being traced by GDB, which we stopped ourselves. */ @@ -128,6 +130,8 @@ thread1_func (void *unused) { int i; + pthread_barrier_wait (&threads_started_barrier); + timed_mutex_lock (&thread1_tid_mutex); /* THREAD1_TID_MUTEX must be already locked to avoid a race. */ @@ -163,6 +167,8 @@ thread2_func (void *unused) { int i; + pthread_barrier_wait (&threads_started_barrier); + timed_mutex_lock (&thread2_tid_mutex); /* THREAD2_TID_MUTEX must be already locked to avoid a race. */ @@ -354,6 +360,8 @@ main (int argc, char **argv) assert_perror (errno); assert (i == 0); + pthread_barrier_init (&threads_started_barrier, NULL, 3); + i = pthread_create (&thread1, NULL, thread1_func, NULL); assert (i == 0); @@ -380,6 +388,11 @@ main (int argc, char **argv) atexit (cleanup); + /* Wait until all threads are seen running. On Linux (at least), + new threads start stopped, and the debugger must resume them. + Need to wait for that before stopping GDB. */ + pthread_barrier_wait (&threads_started_barrier); + printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); if (tracer) diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.c b/gdb/testsuite/gdb.threads/watchthreads-reorder.c index 315104a..05b200c 100644 --- a/gdb/testsuite/gdb.threads/watchthreads-reorder.c +++ b/gdb/testsuite/gdb.threads/watchthreads-reorder.c @@ -44,6 +44,8 @@ static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_ static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; +static pthread_barrier_t threads_started_barrier; + /* These variables must have lower in-memory addresses than thread1_rwatch and thread2_rwatch so that they take their watchpoint slots. */ @@ -87,6 +89,8 @@ thread1_func (void *unused) int i; volatile int rwatch_store; + pthread_barrier_wait (&threads_started_barrier); + timed_mutex_lock (&thread1_tid_mutex); /* THREAD1_TID_MUTEX must be already locked to avoid race. */ @@ -113,6 +117,8 @@ thread2_func (void *unused) int i; volatile int rwatch_store; + pthread_barrier_wait (&threads_started_barrier); + timed_mutex_lock (&thread2_tid_mutex); /* THREAD2_TID_MUTEX must be already locked to avoid race. */ @@ -279,6 +285,8 @@ main (int argc, char **argv) timed_mutex_lock (&terminate_mutex); + pthread_barrier_init (&threads_started_barrier, NULL, 3); + i = pthread_create (&thread1, NULL, thread1_func, NULL); assert (i == 0); @@ -305,6 +313,11 @@ main (int argc, char **argv) atexit (cleanup); + /* Wait until all threads are seen running. On Linux (at least), + new threads start stopped, and the debugger must resume them. + Need to wait for that before stopping GDB. */ + pthread_barrier_wait (&threads_started_barrier); + printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); if (tracer)