aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2014-10-17 13:31:25 +0100
committerPedro Alves <palves@redhat.com>2014-10-17 13:33:30 +0100
commit0ff33695eeedf3c2e8cdec8690ae4a10a66b3389 (patch)
tree7acff2ceeff238fb1700b66bc97cc8ea03b08494
parent6fdebc3d1c54d2202f7637e7345fe6d25c7ed93b (diff)
downloadgdb-0ff33695eeedf3c2e8cdec8690ae4a10a66b3389.zip
gdb-0ff33695eeedf3c2e8cdec8690ae4a10a66b3389.tar.gz
gdb-0ff33695eeedf3c2e8cdec8690ae4a10a66b3389.tar.bz2
PR gdb/17300: Input after "c -a" crashes readline/GDB
If all threads in the target were already running when the user does "c -a", nothing puts the inferior's terminal settings in effect and removes stdin from the event loop, which we must when running a foreground command. The result is that user input afterwards crashes readline/gdb: (gdb) start Temporary breakpoint 1 at 0x4005d4: file continue-all-already-running.c, line 23. Starting program: continue-all-already-running Temporary breakpoint 1, main () at continue-all-already-running.c:23 23 sleep (10); (gdb) c -a& Continuing. (gdb) c -a Continuing. p 1 readline: readline_callback_read_char() called with no handler! Aborted (core dumped) $ Backtrace: Program received signal SIGABRT, Aborted. 0x0000003b36a35877 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); (top-gdb) p 1 $1 = 1 (top-gdb) bt #0 0x0000003b36a35877 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x0000003b36a36f68 in __GI_abort () at abort.c:89 #2 0x0000000000784aa9 in rl_callback_read_char () at readline/callback.c:116 #3 0x0000000000619181 in rl_callback_read_char_wrapper (client_data=0x0) at gdb/event-top.c:167 #4 0x0000000000619557 in stdin_event_handler (error=0, client_data=0x0) at gdb/event-top.c:373 #5 0x000000000061814a in handle_file_event (data=...) at gdb/event-loop.c:763 #6 0x0000000000617631 in process_event () at gdb/event-loop.c:340 #7 0x00000000006176f8 in gdb_do_one_event () at gdb/event-loop.c:404 #8 0x0000000000617748 in start_event_loop () at gdb/event-loop.c:429 #9 0x00000000006191b3 in cli_command_loop (data=0x0) at gdb/event-top.c:182 #10 0x000000000060f538 in current_interp_command_loop () at gdb/interps.c:318 #11 0x0000000000610701 in captured_command_loop (data=0x0) at gdb/main.c:323 #12 0x000000000060c3f5 in catch_errors (func=0x6106e6 <captured_command_loop>, func_args=0x0, errstring=0x9002c1 "", mask=RETURN_MASK_ALL) at gdb/exceptions.c:237 #13 0x0000000000611bff in captured_main (data=0x7fffffffd780) at gdb/main.c:1151 #14 0x000000000060c3f5 in catch_errors (func=0x610afe <captured_main>, func_args=0x7fffffffd780, errstring=0x9002c1 "", mask=RETURN_MASK_ALL) at gdb/exceptions.c:237 #15 0x0000000000611c28 in gdb_main (args=0x7fffffffd780) at gdb/main.c:1159 #16 0x000000000045ef97 in main (argc=5, argv=0x7fffffffd888) at gdb/gdb.c:32 (top-gdb) Tested on x86_64 Fedora 20, native and gdbserver. gdb/ 2014-10-17 Pedro Alves <palves@redhat.com> PR gdb/17300 * infcmd.c (continue_1): If continuing all threads in the foreground, make sure the inferior's terminal settings are put in effect. gdb/testsuite/ 2014-10-17 Pedro Alves <palves@redhat.com> PR gdb/17300 * gdb.base/continue-all-already-running.c: New file. * gdb.base/continue-all-already-running.exp: New file.
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/infcmd.c18
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.base/continue-all-already-running.c25
-rw-r--r--gdb/testsuite/gdb.base/continue-all-already-running.exp79
5 files changed, 135 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0aa52d7..3d0b65a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
2014-10-17 Pedro Alves <palves@redhat.com>
+ PR gdb/17300
+ * infcmd.c (continue_1): If continuing all threads in the
+ foreground, make sure the inferior's terminal settings are put in
+ effect.
+
+2014-10-17 Pedro Alves <palves@redhat.com>
+
PR gdb/17472
* annotate.c (annotate_breakpoints_invalid): Use
target_terminal_our_for_output instead of target_terminal_ours.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0374533..d270664 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -735,6 +735,24 @@ continue_1 (int all_threads)
iterate_over_threads (proceed_thread_callback, NULL);
+ if (sync_execution)
+ {
+ /* If all threads in the target were already running,
+ proceed_thread_callback ends up never calling proceed,
+ and so nothing calls this to put the inferior's terminal
+ settings in effect and remove stdin from the event loop,
+ which we must when running a foreground command. E.g.:
+
+ (gdb) c -a&
+ Continuing.
+ <all threads are running now>
+ (gdb) c -a
+ Continuing.
+ <no thread was resumed, but the inferior now owns the terminal>
+ */
+ target_terminal_inferior ();
+ }
+
/* Restore selected ptid. */
do_cleanups (old_chain);
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6a1d330..27aabc6 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2014-10-17 Pedro Alves <palves@redhat.com>
+ PR gdb/17300
+ * gdb.base/continue-all-already-running.c: New file.
+ * gdb.base/continue-all-already-running.exp: New file.
+
+2014-10-17 Pedro Alves <palves@redhat.com>
+
PR gdb/17472
* gdb.base/annota-input-while-running.c: New file.
* gdb.base/annota-input-while-running.exp: New file.
diff --git a/gdb/testsuite/gdb.base/continue-all-already-running.c b/gdb/testsuite/gdb.base/continue-all-already-running.c
new file mode 100644
index 0000000..a6516d5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/continue-all-already-running.c
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 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 <unistd.h>
+
+int
+main (void)
+{
+ sleep (10);
+ return 0; /* set break here */
+}
diff --git a/gdb/testsuite/gdb.base/continue-all-already-running.exp b/gdb/testsuite/gdb.base/continue-all-already-running.exp
new file mode 100644
index 0000000..6dde730
--- /dev/null
+++ b/gdb/testsuite/gdb.base/continue-all-already-running.exp
@@ -0,0 +1,79 @@
+# Copyright (C) 2014 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/>.
+
+# Test that "c -a" doesn't leave GDB processing input, even if all
+# threads were already running. PR gdb/17300.
+
+standard_testfile
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} $srcfile] } {
+ return -1
+}
+
+gdb_test_no_output "set non-stop on"
+
+if ![runto_main] {
+ return
+}
+
+set linenum [gdb_get_line_number "set break here"]
+gdb_breakpoint "$linenum"
+
+gdb_test "c -a&" "Continuing\\."
+
+set test "no stop"
+gdb_test_multiple "" $test {
+ -timeout 1
+ timeout {
+ pass $test
+ }
+}
+
+# Paranoia. Check that input works after bg command.
+gdb_test "print 1" " = 1"
+
+# Continue in the foreground, and wait one second to make sure the
+# inferior really starts running. If we get a prompt to soon (e.g.,
+# the program stops), this issues a fail.
+set saw_continuing 0
+set test "c -a"
+gdb_test_multiple "c -a" $test {
+ -timeout 1
+ -re "Continuing\\." {
+ set saw_continuing 1
+ exp_continue
+ }
+ timeout {
+ gdb_assert $saw_continuing $test
+ }
+}
+
+# Type something while the inferior is running in the foreground.
+send_gdb "print 2\n"
+
+# Poor buggy GDB would crash before the breakpoint was hit.
+set test "breakpoint hit"
+gdb_test_multiple "" $test {
+ -re "set break here ..\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+
+set test "print command result"
+gdb_test_multiple "" $test {
+ -re " = 2\r\n$gdb_prompt $" {
+ pass $test
+ }
+}