]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Windows gdb: Avoid hang second attach/run
authorPedro Alves <pedro@palves.net>
Fri, 2 Jun 2023 22:08:49 +0000 (23:08 +0100)
committerPedro Alves <pedro@palves.net>
Thu, 7 May 2026 18:50:11 +0000 (19:50 +0100)
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 <tom@tromey.com>
Change-Id: I55b4438795439673c49fa55f55ddf0191f4f0ea8
commit-id: 1caa5be0

gdb/testsuite/gdb.base/attach.exp
gdb/windows-nat.c

index bffdfd9b1aa932a10b2890e6b5011b0f21abe2f2..a4e7d72ef94713c52ebed53cb880f5c3a5f899a2 100644 (file)
@@ -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
index b9d32b6c0c4dc30427dfb761d9d62c4fbc06c60f..d506b42fbdac22aaac6c6a5b411d841f95f6914d 100644 (file)
@@ -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 ();
 }