diff options
Diffstat (limited to 'gdb/testsuite/gdb.threads/thread-specific-bp.exp')
-rw-r--r-- | gdb/testsuite/gdb.threads/thread-specific-bp.exp | 127 |
1 files changed, 127 insertions, 0 deletions
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" |