diff options
author | Pedro Alves <palves@redhat.com> | 2014-07-09 15:59:02 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2014-07-09 15:59:02 +0100 |
commit | 7180e04a36d812bbea2c280f2db33a7e8ce6b07b (patch) | |
tree | 6faeef54a13b3a432c270d02b1cd60d7b2602916 /gdb/infcmd.c | |
parent | 9a9a76082919371f4ceb571f6c9892325b80a2e0 (diff) | |
download | gdb-7180e04a36d812bbea2c280f2db33a7e8ce6b07b.zip gdb-7180e04a36d812bbea2c280f2db33a7e8ce6b07b.tar.gz gdb-7180e04a36d812bbea2c280f2db33a7e8ce6b07b.tar.bz2 |
Fix "attach" command vs user input race
On async targets, a synchronous attach is done like this:
#1 - target_attach is called (PTRACE_ATTACH is issued)
#2 - a continuation is installed
#3 - we go back to the event loop
#4 - target reports stop (SIGSTOP), event loop wakes up, and
attach continuation is called
#5 - among other things, the continuation calls
target_terminal_inferior, which removes stdin from the event
loop
Note that in #3, GDB is still processing user input. If the user is
fast enough, e.g., with something like:
echo -e "attach PID\nset xxx=1" | gdb
... then the "set" command is processed before the attach completes.
We get worse behavior even, if input is a tty and therefore
readline/editing is enabled, with e.g.,:
(gdb) attach PID\nset xxx=1
we then crash readline/gdb, with:
Attaching to program: attach-wait-input, process 14537
readline: readline_callback_read_char() called with no handler!
Aborted
$
Fix this by calling target_terminal_inferior before #3 above.
The test covers both scenarios by running with editing/readline forced
to both on and off.
gdb/
2014-07-09 Pedro Alves <palves@redhat.com>
* infcmd.c (attach_command_post_wait): Don't call
target_terminal_inferior here.
(attach_command): Call it here instead.
gdb/testsuite/
2014-07-09 Pedro Alves <palves@redhat.com>
* gdb.base/attach-wait-input.exp: New file.
* gdb.base/attach-wait-input.c: New file.
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r-- | gdb/infcmd.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 14736a5..021a587 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2380,9 +2380,6 @@ attach_command_post_wait (char *args, int from_tty, int async_exec) post_create_inferior (¤t_target, from_tty); - /* Install inferior's terminal modes. */ - target_terminal_inferior (); - if (async_exec) { /* The user requested an `attach&', so be sure to leave threads @@ -2498,6 +2495,22 @@ attach_command (char *args, int from_tty) based on what modes we are starting it with. */ target_terminal_init (); + /* Install inferior's terminal modes. This may look like a no-op, + as we've just saved them above, however, this does more than + restore terminal settings: + + - installs a SIGINT handler that forwards SIGINT to the inferior. + Otherwise a Ctrl-C pressed just while waiting for the initial + stop would end up as a spurious Quit. + + - removes stdin from the event loop, which we need if attaching + in the foreground, otherwise on targets that report an initial + stop on attach (which are most) we'd process input/commands + while we're in the event loop waiting for that stop. That is, + before the attach continuation runs and the command is really + finished. */ + target_terminal_inferior (); + /* Set up execution context to know that we should return from wait_for_inferior as soon as the target reports a stop. */ init_wait_for_inferior (); |