diff options
author | Pedro Alves <palves@redhat.com> | 2015-08-06 18:22:59 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2015-08-07 17:26:21 +0100 |
commit | d4569d7bc572ae8f10d7c527cbdfbc9d26cc1ed8 (patch) | |
tree | e40ae0ae70e2fad63d20d1c5d37afe6fa084a210 | |
parent | bfedc46af315dc6484295699c35e05040d76d700 (diff) | |
download | gdb-d4569d7bc572ae8f10d7c527cbdfbc9d26cc1ed8.zip gdb-d4569d7bc572ae8f10d7c527cbdfbc9d26cc1ed8.tar.gz gdb-d4569d7bc572ae8f10d7c527cbdfbc9d26cc1ed8.tar.bz2 |
Fix step-over-{trips-on-watchpoint|lands-on-breakpoint}.exp race
On a target that is both always in non-stop mode and can do displaced
stepping (such as native x86_64 GNU/Linux, with "maint set
target-non-stop on"), the step-over-trips-on-watchpoint.exp test
sometimes fails like this:
(gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: thread 1
set scheduler-locking off
(gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: set scheduler-locking off
step
-[Switching to Thread 0x7ffff7fc0700 (LWP 11782)]
-Hardware watchpoint 4: watch_me
-
-Old value = 0
-New value = 1
-child_function (arg=0x0) at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c:39
-39 other = 1; /* set thread-specific breakpoint here */
-(gdb) PASS: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: step
+wait_threads () at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c:49
+49 return 1; /* in wait_threads */
+(gdb) FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: no thread-specific bp: step: step
Note "scheduler-locking" was set off. The problem is that on such
targets, the step-over of thread 2 and the "step" of thread 1 can be
set to run simultaneously (since with displaced stepping the
breakpoint isn't ever removed from the target), and sometimes, the
"step" of thread 1 finishes first, so it'd take another resume to see
the watchpoint trigger. Fix this by replacing the wait_threads
function with a one-line infinite loop that doesn't call any function,
so that the "step" of thread 1 never finishes.
gdb/testsuite/ChangeLog:
2015-08-07 Pedro Alves <palves@redhat.com>
* gdb.threads/step-over-lands-on-breakpoint.c (wait_threads):
Delete function.
(main): Add alarm. Run an infinite loop instead of calling
wait_threads.
* gdb.threads/step-over-lands-on-breakpoint.exp (do_test): Change
comment.
* gdb.threads/step-over-trips-on-watchpoint.c (wait_threads):
Delete function.
(main): Add alarm. Run an infinite loop instead of calling
wait_threads.
* gdb.threads/step-over-trips-on-watchpoint.exp (do_test): Change
comment.
5 files changed, 42 insertions, 22 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 5e4d5e7..db7538a 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,20 @@ 2015-08-07 Pedro Alves <palves@redhat.com> + * gdb.threads/step-over-lands-on-breakpoint.c (wait_threads): + Delete function. + (main): Add alarm. Run an infinite loop instead of calling + wait_threads. + * gdb.threads/step-over-lands-on-breakpoint.exp (do_test): Change + comment. + * gdb.threads/step-over-trips-on-watchpoint.c (wait_threads): + Delete function. + (main): Add alarm. Run an infinite loop instead of calling + wait_threads. + * gdb.threads/step-over-trips-on-watchpoint.exp (do_test): Change + comment. + +2015-08-07 Pedro Alves <palves@redhat.com> + * gdb.base/checkpoint-ns.exp: New file. * gdb.base/checkpoint.exp: Pass explicit "checkpoint.c" to standard_testfile. diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c index 0a6ed8f..2480164 100644 --- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c +++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c @@ -41,23 +41,26 @@ child_function (void *arg) pthread_exit (NULL); } -static int -wait_threads (void) -{ - return 1; /* in wait_threads */ -} - int main () { int res; long i; + alarm (300); + pthread_barrier_init (&barrier, NULL, 2); res = pthread_create (&child_thread, NULL, child_function, NULL); pthread_barrier_wait (&barrier); - wait_threads (); /* set wait-thread breakpoint here */ + + /* Use an infinite loop with no function calls so that "step" over + this line never finishes before the breakpoint in the other + thread triggers. That can happen if the step-over of thread 2 is + done with displaced stepping on a target that is always in + non-stop mode, as in that case GDB runs both threads + simultaneously. */ + while (1); /* set wait-thread breakpoint here */ pthread_join (child_thread, NULL); diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp index 52b59ec..b38f23b 100644 --- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp +++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp @@ -59,9 +59,9 @@ proc do_test {displaced command} { gdb_test_no_output "set scheduler-locking off" # Thread 2 is still stopped at a breakpoint that needs to be - # stepped over before proceeding thread 1. However, right - # where the step-over lands there's another breakpoint - # installed, which should trap and be reported to the user. + # stepped over. However, right where the step-over lands + # there's another breakpoint installed, which should trap and + # be reported to the user. gdb_test "$command" "step-over here.*" } } diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c index 6cf97fb..34ba079 100644 --- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c +++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c @@ -43,23 +43,26 @@ child_function (void *arg) pthread_exit (NULL); } -static int -wait_threads (void) -{ - return 1; /* in wait_threads */ -} - int main () { int res; long i; + alarm (300); + pthread_barrier_init (&barrier, NULL, 2); res = pthread_create (&child_thread, NULL, child_function, NULL); pthread_barrier_wait (&barrier); - wait_threads (); /* set wait-thread breakpoint here */ + + /* Use an infinite loop with no function calls so that "step" over + this line never finishes before the watchpoint in the other + thread triggers. That can happen if the step-over of thread 2 is + done with displaced stepping on a target that is always in + non-stop mode, as in that case GDB runs both threads + simultaneously. */ + while (1); /* set wait-thread breakpoint here */ pthread_join (child_thread, NULL); diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp index 89b66e5..7e27f97 100644 --- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp +++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp @@ -115,11 +115,10 @@ proc do_test { displaced with_bp } { gdb_test "thread 1" "Switching to .*" gdb_test_no_output "set scheduler-locking off" - # Thread 2 is still stopped at a breakpoint that needs to be - # stepped over before proceeding thread 1. However, the - # instruction that is under the breakpoint triggers a - # watchpoint, which should trap and be reported to the - # user. + # Thread 2 is still stopped at a breakpoint that needs + # to be stepped over. However, the instruction that + # is under the breakpoint triggers a watchpoint, which + # should trap and be reported to the user. gdb_test "$command" "Hardware watchpoint.*: watch_me.*New value = 1.*" } } |