[binutils-gdb] Windows gdb: Avoid hang second attach/run

Pedro Alves via Gdb-cvs <[email protected]>
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7a15a5f571da8772765bfb17d1049a097205035e

commit 7a15a5f571da8772765bfb17d1049a097205035e
Author: Pedro Alves <[email protected]>
Date:   Fri Jun 2 23:08:49 2023 +0100

    Windows gdb: Avoid hang second attach/run
    
    gdb.base/attach.exp starts a second inferior and tries to attach the
    second inferior to the same process that inferior 1 is already
    debugging.  The point is to make sure that the backend errors out when
    it tries to attach to a process that is already being debugged.
    
    windows_nat_target::attach and windows_nat_target::create_inferior
    both hang in this situation, because they call into do_synchronously,
    which hangs because the 'process_thread' thread is blocked in
    WaitForDebugEvent.
    
    E.g.:
    
      attach 4420
      FAIL: gdb.base/attach.exp: do_attach_failure_tests: fail to attach again (timeout)
    
    Until the Windows backend is taught to debug multiple processes, which
    will probably require having one process_thread thread per inferior,
    detect the situation and error out before GDB hangs.
    
    This results in the following progression in gdb.base/attach.exp:
    
     -FAIL: gdb.base/attach.exp: do_attach_failure_tests: fail to attach again (timeout)
     -FAIL: gdb.base/attach.exp: do_attach_failure_tests: set confirm off (timeout)
     -FAIL: gdb.base/attach.exp: do_attach_failure_tests: switch to inferior 1 (timeout)
     -FAIL: gdb.base/attach.exp: do_attach_failure_tests: exit after attach failures (timeout)
     -FAIL: gdb.base/attach.exp: do_attach_failure_tests: gdb_breakpoint: set breakpoint at main (timeout)
     -FAIL: gdb.base/attach.exp: do_attach_failure_tests: stop at main (timeout)
     +PASS: gdb.base/attach.exp: do_attach_failure_tests: fail to attach again
     +PASS: gdb.base/attach.exp: do_attach_failure_tests: set confirm off
     +PASS: gdb.base/attach.exp: do_attach_failure_tests: switch to inferior 1
     +PASS: gdb.base/attach.exp: do_attach_failure_tests: exit after attach failures
     +PASS: gdb.base/attach.exp: do_attach_failure_tests: stop at main
    
    There are still other failures not addressed by this patch.
    
    Tests that launch a second program with "run" exist, but are normally
    gated by allow_multi_inferior_tests.
    
    Approved-By: Tom Tromey <[email protected]>
    Change-Id: I55b4438795439673c49fa55f55ddf0191f4f0ea8
    commit-id: 1caa5be0

Diff:
---
 gdb/testsuite/gdb.base/attach.exp |  4 ++++
 gdb/windows-nat.c                 | 19 +++++++++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/gdb/testsuite/gdb.base/attach.exp b/gdb/testsuite/gdb.base/attach.exp
index bffdfd9b1aa..a4e7d72ef94 100644
--- a/gdb/testsuite/gdb.base/attach.exp
+++ b/gdb/testsuite/gdb.base/attach.exp
@@ -175,6 +175,10 @@ proc_with_prefix do_attach_failure_tests {} {
 	    # Response expected when using gdbserver.
 	    pass "$test"
 	}
+	-re -wrap "Can only debug one process at a time\\." {
+	    # Response expected on Windows.
+	    pass "$test"
+	}
     }
 
     # To ensure the target is still alive and working after this, try to run
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index b9d32b6c0c4..d506b42fbda 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2056,14 +2056,24 @@ out:
   return ret;
 }
 
+/* Throw an error if we're already debugging a Windows process.  We
+   can only debug one at a time currently.  */
+
+static void
+ensure_only_one_process ()
+{
+  if (windows_process->process_id != 0)
+    error (_("Can only debug one process at a time."));
+}
+
 /* Attach to process PID, then initialize for debugging it.  */
 
 void
 windows_nat_target::attach (const char *args, int from_tty)
 {
-  DWORD pid;
+  ensure_only_one_process ();
 
-  pid = parse_pid_to_attach (args);
+  DWORD pid = parse_pid_to_attach (args);
 
   if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
     warning ("Failed to get SE_DEBUG_NAME privilege\n"
@@ -2415,6 +2425,8 @@ windows_nat_target::detach (inferior *inf, int from_tty)
   switch_to_no_thread ();
   detach_inferior (inf);
 
+  windows_process->process_id = 0;
+
   maybe_unpush_target ();
 }
 
@@ -2857,6 +2869,8 @@ windows_nat_target::create_inferior (const char *exec_file,
   DWORD flags = 0;
   const std::string &inferior_tty = current_inferior ()->tty ();
 
+  ensure_only_one_process ();
+
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
 
@@ -3166,6 +3180,7 @@ windows_nat_target::mourn_inferior ()
       CHECK (CloseHandle (windows_process->handle));
       windows_process->open_process_used = 0;
     }
+  windows_process->process_id = 0;
   inf_child_target::mourn_inferior ();
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.