diff options
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/breakpoint.c | 18 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.c | 127 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.exp | 40 |
5 files changed, 193 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5d61823..7ea7a02 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2015-08-05 Pedro Alves <palves@redhat.com> + Joel Brobecker <brobecker@adacore.com> + + * breakpoint.c (bpstat_what) <bp_longjmp, bp_longjmp_call_dummy> + <bp_exception, bp_longjmp_resume, bp_exception_resume>: Handle the + case where BS->STOP is not set. + 2015-08-05 Ulrich Weigand <uweigand@de.ibm.com> * nat/gdb_thread_db.h: Add copyright header. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 78a694e..125b22f 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5752,13 +5752,23 @@ bpstat_what (bpstat bs_head) case bp_longjmp: case bp_longjmp_call_dummy: case bp_exception: - this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME; - retval.is_longjmp = bptype != bp_exception; + if (bs->stop) + { + this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME; + retval.is_longjmp = bptype != bp_exception; + } + else + this_action = BPSTAT_WHAT_SINGLE; break; case bp_longjmp_resume: case bp_exception_resume: - this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME; - retval.is_longjmp = bptype == bp_longjmp_resume; + if (bs->stop) + { + this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME; + retval.is_longjmp = bptype == bp_longjmp_resume; + } + else + this_action = BPSTAT_WHAT_SINGLE; break; case bp_step_resume: if (bs->stop) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index f633c11..59d0be7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-08-05 Pedro Alves <palves@redhat.com> + + * gdb.threads/next-while-other-thread-longjmps.c: New file. + * gdb.threads/next-while-other-thread-longjmps.exp: New file. + 2015-08-03 Sandra Loosemore <sandra@codesourcery.com> * gdb.base/bp-permanent.exp: Report test as unsupported if diff --git a/gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.c b/gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.c new file mode 100644 index 0000000..4733b8f --- /dev/null +++ b/gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.c @@ -0,0 +1,127 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <pthread.h> +#include <unistd.h> +#include <setjmp.h> + +/* Number of threads. */ +#define NTHREADS 10 + +/* When set, threads exit. */ +volatile int break_out; + +pthread_barrier_t barrier; + +/* Entry point for threads that setjmp/longjmp. */ + +static void * +thread_longjmp (void *arg) +{ + jmp_buf env; + + pthread_barrier_wait (&barrier); + + while (!break_out) + { + if (setjmp (env) == 0) + longjmp (env, 1); + + usleep (1); + } + return NULL; +} + +/* Entry point for threads that try/catch. */ + +static void * +thread_try_catch (void *arg) +{ + volatile unsigned int counter = 0; + + pthread_barrier_wait (&barrier); + + while (!break_out) + { + try + { + throw 1; + } + catch (...) + { + counter++; + } + + usleep (1); + } + return NULL; +} + +int +main (void) +{ + pthread_t threads[NTHREADS]; + int i; + int ret; + + /* Don't run forever. */ + alarm (180); + + pthread_barrier_init (&barrier, NULL, NTHREADS + 1); + + for (i = 0; i < NTHREADS; i++) + { + /* Half of the threads does setjmp/longjmp, the other half does + try/catch. */ + if ((i % 2) == 0) + ret = pthread_create (&threads[i], NULL, thread_longjmp , NULL); + else + ret = pthread_create (&threads[i], NULL, thread_try_catch , NULL); + assert (ret == 0); + } + + /* Wait until all threads are running. */ + pthread_barrier_wait (&barrier); + +#define LINE usleep (1) + + /* The other thread's setjmp/longjmp/try/catch should not disturb + this thread's stepping over these lines. */ + + LINE; /* set break here */ + LINE; /* line 1 */ + LINE; /* line 2 */ + LINE; /* line 3 */ + LINE; /* line 4 */ + LINE; /* line 5 */ + LINE; /* line 6 */ + LINE; /* line 7 */ + LINE; /* line 8 */ + LINE; /* line 9 */ + LINE; /* line 10 */ + + break_out = 1; + + for (i = 0; i < NTHREADS; i++) + { + ret = pthread_join (threads[i], NULL); + assert (ret == 0); + } + + return 0; +} diff --git a/gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.exp b/gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.exp new file mode 100644 index 0000000..72a0617 --- /dev/null +++ b/gdb/testsuite/gdb.threads/next-while-other-thread-longjmps.exp @@ -0,0 +1,40 @@ +# Copyright (C) 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This test has the main thread step over a few lines, while a few +# threads constantly do setjmp/long and others do try/catch. The +# "next" commands in the main thread should be able to complete +# undisturbed. + +standard_testfile + +set linenum [gdb_get_line_number "set break here"] + +if {[prepare_for_testing "failed to prepare" \ + $testfile $srcfile {c++ debug pthreads}] == -1} { + return -1 +} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_breakpoint $linenum +gdb_continue_to_breakpoint "start line" + +for {set i 1} {$i <= 10} {incr i} { + gdb_test "next" " line $i .*" "next to line $i" +} |