diff --git a/gdb/ChangeLog b/gdb/ChangeLog index aa99da0c4d..0e80cdb2d1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2020-04-21 Tom de Vries + + PR gdb/25471 + * thread.c + (scoped_restore_current_thread::scoped_restore_current_thread): Catch + exception in get_frame_id. + 2020-04-20 Tom Tromey * python/python.c (struct gdbpy_event): Mark move constructor as diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index eee1fa375a..f72256730f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-21 Tom de Vries + + PR gdb/25471 + * gdb.threads/killed-outside.c: New test. + * gdb.threads/killed-outside.exp: New file. + 2020-04-20 Gary Benson * gdb.base/nested-subp1.exp: Use support_nested_function_tests. diff --git a/gdb/testsuite/gdb.threads/killed-outside.c b/gdb/testsuite/gdb.threads/killed-outside.c new file mode 100644 index 0000000000..ac4cf0b07a --- /dev/null +++ b/gdb/testsuite/gdb.threads/killed-outside.c @@ -0,0 +1,64 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020 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 . */ + +#include +#include +#include + +pid_t pid; + +static pthread_barrier_t threads_started_barrier; + +static void +all_started (void) +{ +} + +static void * +fun (void *dummy) +{ + int i; + + pthread_barrier_wait (&threads_started_barrier); + + for (i = 0; i < 180; i++) + sleep (1); + + pthread_exit (NULL); +} + +int +main (void) +{ + int i; + pthread_t thread; + + pid = getpid (); + + pthread_barrier_init (&threads_started_barrier, NULL, 2); + + pthread_create (&thread, NULL, fun, NULL); + + pthread_barrier_wait (&threads_started_barrier); + + all_started (); + + for (i = 0; i < 180; i++) + sleep (1); + + exit (EXIT_SUCCESS); +} diff --git a/gdb/testsuite/gdb.threads/killed-outside.exp b/gdb/testsuite/gdb.threads/killed-outside.exp new file mode 100644 index 0000000000..ff5a115728 --- /dev/null +++ b/gdb/testsuite/gdb.threads/killed-outside.exp @@ -0,0 +1,57 @@ +# Copyright (C) 2020 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 . + +# This test-case tests that continuing an inferior that has been killed +# using an external sigkill does not make gdb misbehave. + +standard_testfile + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ + {pthreads debug}] == -1} { + return -1 +} + +if { ![runto "all_started"] } { + return -1 +} +delete_breakpoints + +set testpid [get_valueof "" "pid" -1 "get pid of inferior"] +if { $testpid == -1 } { + return -1 +} +remote_exec target "kill -9 ${testpid}" + +# Give it some time to die. +sleep 2 + +set no_such_process_msg "Couldn't get registers: No such process\." +set killed_msg "Program terminated with signal SIGKILL, Killed\." +set no_longer_exists_msg "The program no longer exists\." +set not_being_run_msg "The program is not being run\." + +gdb_test_multiple "continue" "prompt after first continue" { + -re "Continuing\.\r\n$no_such_process_msg\r\n$no_such_process_msg\r\n$gdb_prompt " { + pass $gdb_test_name + # Two times $no_such_process_msg. The bug condition was triggered, go + # check for it. + gdb_test_multiple "" "messages" { + -re ".*$killed_msg.*$no_longer_exists_msg\r\n" { + pass $gdb_test_name + gdb_test "continue" $not_being_run_msg "second continue" + } + } + } +} diff --git a/gdb/thread.c b/gdb/thread.c index c6e3d356a5..03805bd256 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1488,8 +1488,16 @@ scoped_restore_current_thread::scoped_restore_current_thread () else frame = NULL; - m_selected_frame_id = get_frame_id (frame); - m_selected_frame_level = frame_relative_level (frame); + try + { + m_selected_frame_id = get_frame_id (frame); + m_selected_frame_level = frame_relative_level (frame); + } + catch (const gdb_exception_error &ex) + { + m_selected_frame_id = null_frame_id; + m_selected_frame_level = -1; + } tp->incref (); m_thread = tp;