# Copyright (C) 2013-2023 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 . # # 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 } # 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 {non_stop} { global gdb_prompt if { ![runto_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 } # Check that multiple uses of 'thread' keyword give an error. gdb_test "break main thread $start_thre thread $main_thre" \ "You can specify only one thread\\." # 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 reachable 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 { $non_stop } { set cmd "continue -a" } else { set cmd "continue" } set test "continue to end" set thread_exited 0 set prompt 0 set msg_re \ [join \ [list \ "Thread-specific breakpoint 3 deleted" \ "-" \ "thread 2 no longer in the thread list\\."]] gdb_test_multiple "$cmd" $test -lbl { -re "(^|\r\n)${msg_re}(?=\r\n)" { if { $prompt } { pass $gdb_test_name } else { set thread_exited 1 exp_continue } } -re "\r\n$gdb_prompt " { if { $thread_exited } { pass $gdb_test_name } else { set prompt 1 exp_continue } } } 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 } } } foreach_with_prefix non_stop {on off} { save_vars { GDBFLAGS } { append GDBFLAGS " -ex \"set non-stop $non_stop\"" clean_restart $binfile } check_thread_specific_breakpoint $non_stop }