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.
This commit is contained in:
Pedro Alves 2014-10-17 13:31:25 +01:00
parent 6fdebc3d1c
commit 0ff33695ee
5 changed files with 135 additions and 0 deletions

View File

@ -1,3 +1,10 @@
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

View File

@ -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);
}

View File

@ -1,3 +1,9 @@
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

View File

@ -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 */
}

View File

@ -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
}
}