]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
linux: handle split resume requests with target-async off users/mmetzger/pr19340
authorMarkus Metzger <markus.t.metzger@intel.com>
Fri, 10 Jan 2025 07:44:22 +0000 (07:44 +0000)
committerMarkus Metzger <markus.t.metzger@intel.com>
Mon, 26 May 2025 07:01:15 +0000 (07:01 +0000)
With

    target-async off
    scheduler-locking off
    schedule-multiple on

and

    record btrace

the record-btrace target splits resume and stop requests when there are
multiple inferiors and some are replaying while others are recording.

Since wait would be blocking in this configuration, we cannot afford to
split wait requests, as well, or risk a hang.

This leads to scenarios where the target beneath record-btrace received

    resume requests for inferiors other than the current inferior, since
    that would be handled by the record target above.

    stop requests, but has not gotten the chance to wait for the
    corresponding event before receiving another resume request.

Handle those cases for the linux native target.

gdb/linux-nat.c

index 7889b2882e15588fe014565d16b0c9ab4e0fafc5..fd3237ad696d1cdd394bf64f37a76ccebdf38234 100644 (file)
@@ -1770,9 +1770,45 @@ linux_nat_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
      last_resume_kind to resume_continue.  */
   iterate_over_lwps (scope_ptid, resume_set_callback);
 
+  /* Let's see if we're supposed to resume INFERIOR_PTID at all.  */
+  if (!inferior_ptid.matches (scope_ptid))
+    {
+      linux_nat_debug_printf ("inferior_ptid %s not in scope %s",
+                             inferior_ptid.to_string ().c_str (),
+                             scope_ptid.to_string ().c_str ());
+      iterate_over_lwps (scope_ptid, [=] (struct lwp_info *info)
+       {
+         return linux_nat_resume_callback (info, nullptr);
+       });
+
+      if (target_can_async_p ())
+       {
+         target_async (true);
+         /* Tell the event loop we have something to process.  */
+         async_file_mark ();
+       }
+
+      return;
+    }
+
   lp = find_lwp_pid (inferior_ptid);
   gdb_assert (lp != NULL);
 
+  if (!lp->stopped)
+    {
+      linux_nat_debug_printf ("inferior_ptid %s not stopped",
+                             inferior_ptid.to_string ().c_str ());
+
+      if (target_can_async_p ())
+       {
+         target_async (true);
+         /* Tell the event loop we have something to process.  */
+         async_file_mark ();
+       }
+
+      return;
+    }
+
   /* Remember if we're stepping.  */
   lp->last_resume_kind = step ? resume_step : resume_continue;