| Message ID | 20260504071636.1571615-6-markus.t.metzger@intel.com |
|---|---|
| State | New |
| Headers |
Return-Path: <gdb-patches-bounces~patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 592414BA9015 for <patchwork@sourceware.org>; Mon, 4 May 2026 07:18:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 592414BA9015 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=Yp9sRxYe X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) by sourceware.org (Postfix) with ESMTPS id 874344BB3BB9 for <gdb-patches@sourceware.org>; Mon, 4 May 2026 07:17:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 874344BB3BB9 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 874344BB3BB9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777879049; cv=none; b=vQh5HvCedCFIKaFlOC2xsfi4sbwipOJgKi5KIYCL411JRxmvfMW1RJf8UPjQmIUutTJ6FjCQzVyNgNpI/gYVbcmaZwNVqBwHAwazMu3baLSEDHb1rEyogCMK7ZzrAUbGxcAGhasiRVS8+Lw59gllA3Fz1n2dPJKDde+e9WPkJOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777879049; c=relaxed/simple; bh=7CAaDNVcQFnxWcFANw0G3bDNOVFwAQVP63zkTx/8PPA=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=grz3V/BkF3Zwbw029RpdqOA4GTZ02bk9w3Y2i3GgjO3BGj/xIpQZ4coWgsrR9ldUzOwm3duKY5fKknIvWft7mRzpP2/PiOVYJ3bbJ5SOh+aXURUA2YdNubEmXDjkNGWNHMAzdtQBbFSqnj+aVKLePjGk9WPHpgpYrdFklscpAMQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 874344BB3BB9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1777879049; x=1809415049; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=7CAaDNVcQFnxWcFANw0G3bDNOVFwAQVP63zkTx/8PPA=; b=Yp9sRxYeSgSxl7BDWcdNBRD8e2xNU71+UXwKJLDwbkpcyMbQUZOo6a2v +mkwnFNzyL6Hm/ZtrqW4QFMDjKxVF3iQLUHXEIcVueLVht7c6SnF5p3kL Cr3PDb04PDhWStoCu+8vTBrGJj0gOrt+HYGFOBvwKcf/G1Jo+rZtXQUf2 aHs0w8vV95uZQZLUQ6Ru5lETgb/17agHtkGSltS/elEWCTBNWdpE+2CNR Wz2HUsOWjqRT5d8wcHMIDwmuz01LkEnxHFV6Jcvj7vutyilEqpnyVYzkg 1Hm+QpIUn++tCYSaUcT7wU8aWbRxwzAAFgUGb3cXWsjBI6CMRWLNAbNhU Q==; X-CSE-ConnectionGUID: JYfpO4AjQl6O6yCaldUYDg== X-CSE-MsgGUID: RFInPdrESNyYMh3CiifRPA== X-IronPort-AV: E=McAfee;i="6800,10657,11775"; a="78926061" X-IronPort-AV: E=Sophos;i="6.23,215,1770624000"; d="scan'208";a="78926061" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 May 2026 00:17:27 -0700 X-CSE-ConnectionGUID: T/qjSQsqSXamG9mp4Zu7pA== X-CSE-MsgGUID: kY2z5pDJTuWRtDg3g5danw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,215,1770624000"; d="scan'208";a="237221371" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 May 2026 00:16:57 -0700 From: Markus Metzger <markus.t.metzger@intel.com> To: gdb-patches@sourceware.org Subject: [PATCH] gdb: use correct target in notify_thread_exited() Date: Mon, 4 May 2026 07:16:35 +0000 Message-Id: <20260504071636.1571615-6-markus.t.metzger@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260504071636.1571615-1-markus.t.metzger@intel.com> References: <20260504071636.1571615-1-markus.t.metzger@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list <gdb-patches.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/gdb-patches>, <mailto:gdb-patches-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/gdb-patches/> List-Post: <mailto:gdb-patches@sourceware.org> List-Help: <mailto:gdb-patches-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/gdb-patches>, <mailto:gdb-patches-request@sourceware.org?subject=subscribe> Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org |
| Series |
gdb: use correct target in notify_thread_exited()
|
|
Commit Message
Metzger, Markus T
May 4, 2026, 7:16 a.m. UTC
clean_up_just_stopped_threads_fsms() may call notify_thread_exited() in
the context of a thread from a different target. In my case:
at .../gdb/thread.c:404
exit_code=std::optional [no contained value], silent=false)
at .../gdb/thread.c:436
exit_code=std::optional [no contained value], silent=false)
at .../gdb/thread.c:733
at .../gdb/thread.c:763
at .../gdb/infrun.c:4548
at .../gdb/infrun.c:4786
Instead of relying on global state, use the exited thread's inferior's
target, which is exactly the target we want.
---
gdb/thread.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
Comments
On 5/4/26 3:16 AM, Markus Metzger wrote: > clean_up_just_stopped_threads_fsms() may call notify_thread_exited() in > the context of a thread from a different target. In my case: > > at .../gdb/thread.c:404 > exit_code=std::optional [no contained value], silent=false) > at .../gdb/thread.c:436 > exit_code=std::optional [no contained value], silent=false) > at .../gdb/thread.c:733 > at .../gdb/thread.c:763 > at .../gdb/infrun.c:4548 > at .../gdb/infrun.c:4786 This is missing the function names, so not very useful. > > Instead of relying on global state, use the exited thread's inferior's > target, which is exactly the target we want. > --- > gdb/thread.c | 6 ++++-- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/gdb/thread.c b/gdb/thread.c > index 74124596b28..5c3b60b2aa7 100644 > --- a/gdb/thread.c > +++ b/gdb/thread.c > @@ -203,14 +203,16 @@ notify_thread_exited (thread_info *t, std::optional<ULONGEST> exit_code, > { > if (!silent && print_thread_events) > { > + struct target_ops *target = t->inf->top_target (); > + > if (exit_code.has_value ()) > gdb_printf (_("[%s (id %s) exited with code %s]\n"), > - target_pid_to_str (t->ptid).c_str (), > + target->pid_to_str (t->ptid).c_str (), > print_thread_id (t), > pulongest (*exit_code)); > else > gdb_printf (_("[%s (id %s) exited]\n"), > - target_pid_to_str (t->ptid).c_str (), > + target->pid_to_str (t->ptid).c_str (), > print_thread_id (t)); This is unfortunately not correct, because target calls (annoyingly IMO) use the target stack of the current inferior to find the target beneath. If you are having to do this change, it means that this function is called for a thread of inferior A, while inferior B is the current one. What will happen is that you'll start with the top target of inferior A, but if that target calls "target_ops::beneath()" to delegate to the target beneath, that will jump to a target of inferior B. If the pid_to_str operation is handled by the top target of inferior A, it will work, but not in the general case. As of today, the only fix for that would be to temporarily switch inferior. I once made a prototype [1] of passing down the target stack explicitly to all target functions. It would be quite invasive, but I don't see any other solution if we want to lift that "target calls care about current inferior" limitation. Simon [1] https://review.lttng.org/c/binutils-gdb/+/5627
Hello Simon, >On 5/4/26 3:16 AM, Markus Metzger wrote: >> clean_up_just_stopped_threads_fsms() may call notify_thread_exited() in >> the context of a thread from a different target. In my case: >> >> at .../gdb/thread.c:404 >> exit_code=std::optional [no contained value], silent=false) >> at .../gdb/thread.c:436 >> exit_code=std::optional [no contained value], silent=false) >> at .../gdb/thread.c:733 >> at .../gdb/thread.c:763 >> at .../gdb/infrun.c:4548 >> at .../gdb/infrun.c:4786 > >This is missing the function names, so not very useful. I removed it in v2. >> Instead of relying on global state, use the exited thread's inferior's >> target, which is exactly the target we want. >> --- >> gdb/thread.c | 6 ++++-- >> 1 file changed, 4 insertions(+), 2 deletions(-) >> >> diff --git a/gdb/thread.c b/gdb/thread.c >> index 74124596b28..5c3b60b2aa7 100644 >> --- a/gdb/thread.c >> +++ b/gdb/thread.c >> @@ -203,14 +203,16 @@ notify_thread_exited (thread_info *t, >std::optional<ULONGEST> exit_code, >> { >> if (!silent && print_thread_events) >> { >> + struct target_ops *target = t->inf->top_target (); >> + >> if (exit_code.has_value ()) >> gdb_printf (_("[%s (id %s) exited with code %s]\n"), >> - target_pid_to_str (t->ptid).c_str (), >> + target->pid_to_str (t->ptid).c_str (), >> print_thread_id (t), >> pulongest (*exit_code)); >> else >> gdb_printf (_("[%s (id %s) exited]\n"), >> - target_pid_to_str (t->ptid).c_str (), >> + target->pid_to_str (t->ptid).c_str (), >> print_thread_id (t)); > >This is unfortunately not correct, because target calls (annoyingly IMO) >use the target stack of the current inferior to find the target beneath. >If you are having to do this change, it means that this function is >called for a thread of inferior A, while inferior B is the current one. >What will happen is that you'll start with the top target of inferior A, >but if that target calls "target_ops::beneath()" to delegate to the >target beneath, that will jump to a target of inferior B. If the >pid_to_str operation is handled by the top target of inferior A, it will >work, but not in the general case. > >As of today, the only fix for that would be to temporarily switch >inferior. Those scoped_restore_foo are everywhere. I tried to not rely on global state and instead use the arguments passed to the function, but I see now how this cannot work. Makes you wonder why we even bother passing thread_info * and inferior *. I switch to the exited thread in v2. >I once made a prototype [1] of passing down the target stack explicitly to >all target functions. It would be quite invasive, but I don't see any >other solution if we want to lift that "target calls care about current >inferior" limitation. > >[1] https://review.lttng.org/c/binutils-gdb/+/5627 It's every call to inferior_thread() and current_inferior(), too. Regards, Markus. Intel Deutschland GmbH Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany Tel: +49 89 991 430, www.intel.de Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell Chairperson of the Supervisory Board: Nicole Lau Registered Seat: Munich Commercial Register: Amtsgericht Muenchen HRB 186928
On 2026-05-05 03:56, Metzger, Markus T wrote: >> This is unfortunately not correct, because target calls (annoyingly IMO) >> use the target stack of the current inferior to find the target beneath. >> If you are having to do this change, it means that this function is >> called for a thread of inferior A, while inferior B is the current one. >> What will happen is that you'll start with the top target of inferior A, >> but if that target calls "target_ops::beneath()" to delegate to the >> target beneath, that will jump to a target of inferior B. If the >> pid_to_str operation is handled by the top target of inferior A, it will >> work, but not in the general case. >> >> As of today, the only fix for that would be to temporarily switch >> inferior. > > Those scoped_restore_foo are everywhere. I tried to not rely on > global state and instead use the arguments passed to the function, > but I see now how this cannot work. Makes you wonder why we > even bother passing thread_info * and inferior *. Indeed, if a random function takes an inferior parameter but also requires that this inferior is the current one, it can be misleading. It makes you think that it is global-context-agnostic, while it is not. I try not to do this. I would say that this "target calls rely on current inferior's target stack" is the major blocker for continuing doing cleanups to pass context through parameters, rather than global variables. > I switch to the exited thread in v2. > >> I once made a prototype [1] of passing down the target stack explicitly to >> all target functions. It would be quite invasive, but I don't see any >> other solution if we want to lift that "target calls care about current >> inferior" limitation. >> >> [1] https://review.lttng.org/c/binutils-gdb/+/5627 > > It's every call to inferior_thread() and current_inferior(), too. I am not sure what you mean here, those are just simple getters. Simon
Hello Simon, >> It's every call to inferior_thread() and current_inferior(), too. > >I am not sure what you mean here, those are just simple getters. I meant that they get global state while it would be cleaner to pass the inferior or thread as argument. If some function you end up calling uses inferior_thread(), you're still required to switch to that thread and back. It would be nice if the current thread and inferior were UI local state. Markus. Intel Deutschland GmbH Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany Tel: +49 89 991 430, www.intel.de Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell Chairperson of the Supervisory Board: Nicole Lau Registered Seat: Munich Commercial Register: Amtsgericht Muenchen HRB 186928
diff --git a/gdb/thread.c b/gdb/thread.c index 74124596b28..5c3b60b2aa7 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -203,14 +203,16 @@ notify_thread_exited (thread_info *t, std::optional<ULONGEST> exit_code, { if (!silent && print_thread_events) { + struct target_ops *target = t->inf->top_target (); + if (exit_code.has_value ()) gdb_printf (_("[%s (id %s) exited with code %s]\n"), - target_pid_to_str (t->ptid).c_str (), + target->pid_to_str (t->ptid).c_str (), print_thread_id (t), pulongest (*exit_code)); else gdb_printf (_("[%s (id %s) exited]\n"), - target_pid_to_str (t->ptid).c_str (), + target->pid_to_str (t->ptid).c_str (), print_thread_id (t)); }