]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/17347 - Regression: GDB stopped on run with attached process
authorPedro Alves <palves@redhat.com>
Thu, 11 Sep 2014 12:04:15 +0000 (13:04 +0100)
committerPedro Alves <palves@redhat.com>
Thu, 11 Sep 2014 12:16:26 +0000 (13:16 +0100)
Doing:

  gdb --pid=PID -ex run

Results in GDB getting a SIGTTIN, and thus ending stopped.  That's
usually indicative of a missing target_terminal_ours call.

E.g., from the PR:

 $ sleep 1h & p=$!; sleep 0.1; gdb -batch sleep $p -ex run
 [1] 28263
 [1]   Killed                  sleep 1h

 [2]+  Stopped                 gdb -batch sleep $p -ex run

The workaround is doing:

 gdb -ex "attach $PID" -ex "run"

instead of

 gdb [-p] $PID -ex "run"

With the former, gdb waits for the attach command to complete before
moving on to the "run" command, because the interpreter is in sync
mode at this point, within execute_command.  But for the latter,
attach_command is called directly from captured_main, and thus misses
that waiting.  IOW, "run" is running before the attach continuation
has run, before the program stops and attach completes.  The broken
terminal settings are just one symptom of that.  Any command that
queries or requires input results in the same.

The fix is to wait in catch_command_errors (which is specific to
main.c nowadays), just like we wait in execute_command.

gdb/ChangeLog:
2014-09-11  Pedro Alves  <palves@redhat.com>

PR gdb/17347
* main.c: Include "infrun.h".
(catch_command_errors, catch_command_errors_const): Wait for the
foreground command to complete.
* top.c (maybe_wait_sync_command_done): New function, factored out
from ...
(maybe_wait_sync_command_done): ... here.
* top.h (maybe_wait_sync_command_done): New declaration.

gdb/testsuite/ChangeLog:
2014-09-11  Pedro Alves  <palves@redhat.com>

PR gdb/17347
* lib/gdb.exp (gdb_spawn_with_cmdline_opts): New procedure.
* gdb.base/attach.exp (test_command_line_attach_run): New
procedure.
(top level): Call it.

gdb/ChangeLog
gdb/main.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/attach.exp
gdb/testsuite/lib/gdb.exp
gdb/top.c
gdb/top.h

index a8374c7ca171f45013295f64cc45aa4c1d322f28..242fe262437225e94300d04e1f511d66b238660a 100644 (file)
@@ -1,3 +1,14 @@
+2014-09-11  Pedro Alves  <palves@redhat.com>
+
+       PR gdb/17347
+       * main.c: Include "infrun.h".
+       (catch_command_errors, catch_command_errors_const): Wait for the
+       foreground command to complete.
+       * top.c (maybe_wait_sync_command_done): New function, factored out
+       from ...
+       (maybe_wait_sync_command_done): ... here.
+       * top.h (maybe_wait_sync_command_done): New declaration.
+
 2014-09-09  Doug Evans  <xdje42@gmail.com>
 
        PR guile/17367
index ea66fe57cbbb9ae4c695f977dc7e49257bef950a..3a4e40260eda45fc29965d201ff973016f881df3 100644 (file)
@@ -46,6 +46,7 @@
 #include "filenames.h"
 #include "filestuff.h"
 #include "event-top.h"
+#include "infrun.h"
 
 /* The selected interpreter.  This will be used as a set command
    variable, so it should always be malloc'ed - since
@@ -349,7 +350,11 @@ catch_command_errors (catch_command_errors_ftype *command,
 
   TRY_CATCH (e, mask)
     {
+      int was_sync = sync_execution;
+
       command (arg, from_tty);
+
+      maybe_wait_sync_command_done (was_sync);
     }
   return handle_command_errors (e);
 }
@@ -368,7 +373,11 @@ catch_command_errors_const (catch_command_errors_const_ftype *command,
 
   TRY_CATCH (e, mask)
     {
+      int was_sync = sync_execution;
+
       command (arg, from_tty);
+
+      maybe_wait_sync_command_done (was_sync);
     }
   return handle_command_errors (e);
 }
index a3881943d3ea5005dc7e9a56ffd46dbbc35987eb..3d24531cd19e211c611144fdb202faf0a898d865 100644 (file)
@@ -1,3 +1,11 @@
+2014-09-11  Pedro Alves  <palves@redhat.com>
+
+       PR gdb/17347
+       * lib/gdb.exp (gdb_spawn_with_cmdline_opts): New procedure.
+       * gdb.base/attach.exp (test_command_line_attach_run): New
+       procedure.
+       (top level): Call it.
+
 2014-09-11  Pedro Alves  <palves@redhat.com>
 
        * lib/gdb.exp (spawn_wait_for_attach): New procedure.
index a20c51a1921f75e880246991bda60b2c33d8ab69..634049608e12c85e25076f3c8ee538c18b1e5a53 100644 (file)
@@ -396,6 +396,49 @@ proc do_command_attach_tests {} {
     remote_exec build "kill -9 ${testpid}"
 }
 
+# Test ' gdb --pid PID -ex "run" '.  GDB used to have a bug where
+# "run" would run before the attach finished - PR17347.
+
+proc test_command_line_attach_run {} {
+    global gdb_prompt
+    global binfile
+
+    if ![isnative] then {
+       unsupported "commandline attach run test"
+       return 0
+    }
+
+    with_test_prefix "cmdline attach run" {
+       set testpid [spawn_wait_for_attach $binfile]
+
+       set test "run to prompt"
+       gdb_exit
+
+       set res [gdb_spawn_with_cmdline_opts \
+                    "-iex \"set height 0\" -iex \"set width 0\" --pid=$testpid -ex \"start\""]
+       if { $res != 0} {
+           fail $test
+           return $res
+       }
+       gdb_test_multiple "" $test {
+           -re {Attaching to.*Start it from the beginning\? \(y or n\) } {
+               pass $test
+           }
+       }
+
+       send_gdb "y\n"
+
+       set test "run to main"
+       gdb_test_multiple "" $test {
+           -re "Temporary breakpoint .* main .*$gdb_prompt $" {
+               pass $test
+           }
+       }
+
+       # Get rid of the process
+       remote_exec build "kill -9 ${testpid}"
+    }
+}
 
 # Start with a fresh gdb
 
@@ -420,4 +463,6 @@ do_call_attach_tests
 
 do_command_attach_tests
 
+test_command_line_attach_run
+
 return 0
index e2ee110caf2cea56dda2eb2af1536f7eb60195a4..fe317183e052469d7345c8eeed36d7bcbe3fb31d 100644 (file)
@@ -3310,6 +3310,22 @@ proc gdb_spawn { } {
     default_gdb_spawn
 }
 
+# Spawn GDB with CMDLINE_FLAGS appended to the GDBFLAGS global.
+
+proc gdb_spawn_with_cmdline_opts { cmdline_flags } {
+    global GDBFLAGS
+
+    set saved_gdbflags $GDBFLAGS
+
+    append GDBFLAGS $cmdline_flags
+
+    set res [gdb_spawn]
+
+    set GDBFLAGS $saved_gdbflags
+
+    return $res
+}
+
 # Start gdb running, wait for prompt, and disable the pagers.
 
 # Overridable function -- you can override this function in your
index e455624a6db392e2794b71923d33f458722c8aae..42d5467c4ac19f69b405f3d0865615b731a5f404 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -375,6 +375,23 @@ check_frame_language_change (void)
     }
 }
 
+/* See top.h.  */
+
+void
+maybe_wait_sync_command_done (int was_sync)
+{
+  /* If the interpreter is in sync mode (we're running a user
+     command's list, running command hooks or similars), and we
+     just ran a synchronous command that started the target, wait
+     for that command to end.  */
+  if (!interpreter_async && !was_sync && sync_execution)
+    {
+      while (gdb_do_one_event () >= 0)
+       if (!sync_execution)
+         break;
+    }
+}
+
 /* Execute the line P as a command, in the current user context.
    Pass FROM_TTY as second argument to the defining function.  */
 
@@ -461,16 +478,7 @@ execute_command (char *p, int from_tty)
       else
        cmd_func (c, arg, from_tty);
 
-      /* If the interpreter is in sync mode (we're running a user
-        command's list, running command hooks or similars), and we
-        just ran a synchronous command that started the target, wait
-        for that command to end.  */
-      if (!interpreter_async && !was_sync && sync_execution)
-       {
-         while (gdb_do_one_event () >= 0)
-           if (!sync_execution)
-             break;
-       }
+      maybe_wait_sync_command_done (was_sync);
 
       /* If this command has been post-hooked, run the hook last.  */
       execute_cmd_post_hook (c);
index c322c3332380c803cb25131000e6b298604d69e8..94f6c488030ec81bdd55d40473b562fe2f660778 100644 (file)
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -42,6 +42,14 @@ extern void quit_command (char *, int);
 extern void quit_cover (void);
 extern void execute_command (char *, int);
 
+/* If the interpreter is in sync mode (we're running a user command's
+   list, running command hooks or similars), and we just ran a
+   synchronous command that started the target, wait for that command
+   to end.  WAS_SYNC indicates whether sync_execution was set before
+   the command was run.  */
+
+extern void maybe_wait_sync_command_done (int was_sync);
+
 extern void check_frame_language_change (void);
 
 /* Prepare for execution of a command.