diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/breakpoint.c | 25 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/thread-specific-bp.c | 40 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/thread-specific-bp.exp | 127 |
5 files changed, 208 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cf0ff44..c07579c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2013-09-17 Muhammad Waqas <mwaqas@codesourcery.com> + Pedro Alves <palves@redhat.com> + + PR gdb/11568 + * breakpoint.c (remove_threaded_breakpoints): New function. + (_initialize_breakpoint): Attach remove_threaded_breakpoints + as thread_exit observer. + 2013-09-17 Pedro Alves <palves@redhat.com> PR gdb/15911 diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 44bb7a8..734dfd6 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2928,6 +2928,30 @@ remove_breakpoints (void) return val; } +/* When a thread exits, remove breakpoints that are related to + that thread. */ + +static void +remove_threaded_breakpoints (struct thread_info *tp, int silent) +{ + struct breakpoint *b, *b_tmp; + + ALL_BREAKPOINTS_SAFE (b, b_tmp) + { + if (b->thread == tp->num) + { + b->disposition = disp_del_at_next_stop; + + printf_filtered (_("\ +Thread-specific breakpoint %d deleted - thread %d is gone.\n"), + b->number, tp->num); + + /* Hide it from the user. */ + b->number = 0; + } + } +} + /* Remove breakpoints of process PID. */ int @@ -16587,4 +16611,5 @@ agent-printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ automatic_hardware_breakpoints = 1; observer_attach_about_to_proceed (breakpoint_about_to_proceed); + observer_attach_thread_exit (remove_threaded_breakpoints); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ac3aed2..73d71ba 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2013-09-17 Muhammad Waqas <mwaqas@codesourccery.com> + Jan Kratochvil <jan.kartochvil@redhat.com> + Pedro Alves <palves@redhat.com> + + PR gdb/11568 + * gdb.thread/thread-specific-bp.c: New file. + * gdb.thread/thread-specific-bp.exp: New file. + 2013-09-17 Sergio Durigan Junior <sergiodj@redhat.com> * gdb.base/defaults.exp (<show_conv_list>): Add check for $_isvoid diff --git a/gdb/testsuite/gdb.threads/thread-specific-bp.c b/gdb/testsuite/gdb.threads/thread-specific-bp.c new file mode 100644 index 0000000..03831c6 --- /dev/null +++ b/gdb/testsuite/gdb.threads/thread-specific-bp.c @@ -0,0 +1,40 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 <pthread.h> + +static void * +start (void *arg) +{ + return NULL; +} + +static void +end (void) +{ +} + +int +main (void) +{ + pthread_t thread; + + pthread_create (&thread, NULL, start, NULL); + pthread_join (thread, NULL); + end (); + return 0; +} diff --git a/gdb/testsuite/gdb.threads/thread-specific-bp.exp b/gdb/testsuite/gdb.threads/thread-specific-bp.exp new file mode 100644 index 0000000..9f7d142 --- /dev/null +++ b/gdb/testsuite/gdb.threads/thread-specific-bp.exp @@ -0,0 +1,127 @@ +# Copyright (C) 2013 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/>. +# +# Verify that a thread-specific breakpoint is deleted when the +# corresponding thread is gone. + +standard_testfile + +if {[gdb_compile_pthreads \ + "${srcdir}/${subdir}/${srcfile}" \ + "${binfile}" executable {debug} ] != "" } { + return -1 +} + +clean_restart ${binfile} + +# Extract and return the thread ID of the thread stopped at function +# FUNC. + +proc get_thread_id {func} { + global gdb_prompt + + set thre -1 + set test "get $func thread id" + gdb_test_multiple "info threads" $test { + -re "(\[0-9\]+)\[^\n\r\]*Thread\[^\n\r\]*$func.*$gdb_prompt $" { + # Get the thread's id. + set thre $expect_out(1,string) + pass $test + } + } + + return $thre +} + +proc check_thread_specific_breakpoint {mode} { + with_test_prefix "$mode" { + global gdb_prompt + + if ![runto_main] { + untested "could not run to main" + return -1 + } + + set main_thre [get_thread_id "main"] + if { $main_thre < 0 } { + return -1 + } + + gdb_breakpoint "start" + gdb_continue_to_breakpoint "start" + + set start_thre [get_thread_id "start"] + if { $start_thre < 0 } { + return -1 + } + + # Set a thread-specific breakpoint at "main". This can't ever + # be hit, but that's OK. + gdb_breakpoint "main thread $start_thre" + gdb_test "info break" ".*breakpoint.*thread $start_thre" "breakpoint set" + + # Set breakpoint at a place only reacheable after the "start" + # thread exits. + gdb_breakpoint "end" + + # Switch back to the main thread, and resume all threads. The + # "start" thread exits, and the main thread reaches "end". + gdb_test "thread $main_thre" \ + "Switching to thread $main_thre.*" \ + "thread $main_thre selected" + + if { $mode == "non-stop" } { + set cmd "continue -a" + } else { + set cmd "continue" + } + gdb_test "$cmd" \ + "Breakpoint .* end .* at .*" \ + "continue to end" + + # Force GDB to update the thread list. Otherwise, depending + # on target, GDB may not realize that the start thread has + # exited and thus not remove the thread specific breakpoint. + set test "thread start is gone" + gdb_test_multiple "info threads" $test { + -re "\[0-9\]+.*start.*$gdb_prompt $" { + fail $test + } + -re "$gdb_prompt $" { + pass $test + } + } + + set test "thread-specific breakpoint was deleted" + gdb_test_multiple "info breakpoint" $test { + -re "thread $start_thre\n$gdb_prompt $" { + fail $test + } + -re "$gdb_prompt $" { + pass $test + } + } + } +} + +# Test all-stop mode. +check_thread_specific_breakpoint "all-stop" + +clean_restart ${binfile} + +# Test non-stop mode. +gdb_test_no_output "set target-async on" "set async mode" +gdb_test_no_output "set non-stop on" "set non-stop mode" +check_thread_specific_breakpoint "non-stop" |