From: "Metzger, Markus T" <markus.t.metzger@intel.com>
To: Simon Marchi <simark@simark.ca>
Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Subject: RE: [PATCH] gdb: fix an issue with thread list corruption
Date: Thu, 7 May 2026 07:36:27 +0000 [thread overview]
Message-ID: <DM8PR11MB5749F36B55336CB756E7B8ABDE3C2@DM8PR11MB5749.namprd11.prod.outlook.com> (raw)
In-Reply-To: <81a1a827-5c22-4f24-852a-1c85d09c30cc@simark.ca>
Hello Simon,
>>>>> On 5/4/26 3:16 AM, Markus Metzger wrote:
>>>>>> When resuming a target in non-stop mode with 'c -a', the continue
>>>>> command
>>>>>> uses for_each_thread() to proceed each stopped thread individually.
>This
>>>>>> uses an all_threads_safe() iteration.
>>>>>>
>>>>>> If one of the stopped threads does an inline step-over, since the target
>>>>>> is non-stop, we stop_all_threads(), which involves update_thread_list(),
>>>>>> which, in turn, may delete_thread().
>>>>>>
>>>>>> If this deleted the thread pointed to by the m_next safe iterator
>member,
>>>>>> the above all_threads_safe() iteration will be corrupted.
>>>>>>
>>>>>> The thread we're proceeding is stopped and there is no reason to
>delete
>>>>>> it. Consequently, there is no reason for all_threads_safe(), which isn't
>>>>>> that safe in this scenario.
>>>>>>
>>>>>> Iterate using all_threads() and inline proceed_thread_callback().
>>>>>
>>>>> Just to try to make sure I understand the circumstances that lead the
>>>>> the failure correcty (and make sure this doesn't just cover up other
>>>>> problems):
>>>>>
>>>>> - thread 1 is stopped on a breakpoint
>>>>> - thread 2 is executing
>>>>> - displaced stepping is disabled
>>>>> - the target doesn't report thread events to the core
>>>>> - you "continue -a"
>>>>> - thread 1 starts an inline step-over, which calls stop_all_threads,
>>>>> which calls update_thread_list
>>>>> - meanwhile, thread 2 exits
>>>>> - update_thread_list causes thread 2 to be deleted
>>>>> - the safe iterator's m_next field now points to a deleted thread info
>>>
>>> Can you comment on whether the sequence of events above sounds
>correct?
>>> If it is, I think it would be possible to write a CPU test to reproduce
>>> it, that would be helpful along with the fix.
>>
>> The sequence sounds good, but I wonder how we would ensure that thread
>2
>> exits just when we need it to.
>
>Usually, by hammering. But I think it's not as difficult as it sounds.
>The state before the "continue -a" on thread N is that GDB knows about
>thread N+1. Assuming that thread N+1 is a short-lived thread (one that
>does nothing but exit), it exits even before the "continue -a" is
>issued, but GDB doesn't know that until the next thread list update.
>When you "continue -a", GDB iterates using all_threads_safe, without
>doing any thread list update. When iteration reaches thread N, the next
>thread is N+1, exited on the target but it still exists in GDB's mind.
>Thread N starts its inline step-over, and etc etc until the crash.
>
>> This is non-stop mode, so we should learn about the exit immediately.
>> The test would also need to rely on the ordering of threads in the
>> thread list. And detecting the issue requires the next pointer of the
>> next element to be overwritten in a way that causes a deterministic
>> effect - like crashing GDB. We wouldn't want to add another test that
>> fails sporadically.
>
>I wrote a test that fails consistently (at least with ASan) with
>the board native-extended-gdbserver:
>
>https://review.lttng.org/c/binutils-gdb/+/17704
>
> (gdb) PASS: gdb.threads/continue-a-step-over-other-thread-exit.exp:
>step_over_thread_slot=1: continue to break_here
> continue -a
> Continuing.
>
>=================================================================
> ==1250831==ERROR: AddressSanitizer: heap-use-after-free on address
>0x7d0984eb4480 at pc 0x564f8b3da4dd bp 0x7ffdad6a63d0 sp
>0x7ffdad6a63c0
>
>With your fixes, it passes.
And what happens without ASan? Do we introduce yet another sporadically failing test?
If we only created two additional threads, we could vary which thread we're stepping
in two different runs of the test program, which makes the test program fairly trivial.
We'd need to step from one pthread_create() to the next to guarantee the order in
which GDB adds the threads. As long as GDB adds them to either the front or the
back of the thread list consistently, we would get the same order in the two runs,
and by varying the thread we're stepping, we would cover both possible orders.
But we wouldn't be able to guarantee that the other thread exited at just the right
moment, would we? We try to mitigate that by repeating this 100 times, but this is
just asking for the test to fail sporadically at a random iteration - or pass.
We have too many such tests already. They may indicate an actual problem, or maybe
the test itself is broken or inherently non-deterministic. What such tests definitely do is
create noise when trying to test a completely unrelated patch, thus slowing down GDB
development.
To get this deterministic, one would need to mock the remote target to guarantee
the ordering of thread exit and step completion events. Something like gdbreplay,
but with hand-written logs, which would need to be maintained whenever anything
in the remote communication changes. For more substantial changes to the remote
communication, this could become a significant burden.
And without additional tooling, like ASan, we still wouldn't be able to fail deterministically.
>Feel free to check it out and add it to your patch. It will need a bit
>of cleanup, and there is a FIXME saying that it won't work with
>native-gdbserver because it requires inferior args. I have another
>patch series that I need to send that add the ability to pass inferior
>args when using native-gdbserver, I'll try to get that done.
>
>Simon
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
next prev parent reply other threads:[~2026-05-07 7:37 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-04 7:16 [PATCH] gdb, btrace: fix wrong #endif comments Markus Metzger
2026-05-04 7:16 ` [PATCH] gdb: fix an issue with thread list corruption Markus Metzger
2026-05-04 15:30 ` Simon Marchi
2026-05-05 5:04 ` Metzger, Markus T
2026-05-05 15:51 ` Simon Marchi
2026-05-06 5:43 ` Metzger, Markus T
2026-05-06 18:36 ` Simon Marchi
2026-05-07 7:36 ` Metzger, Markus T [this message]
2026-05-07 15:11 ` Simon Marchi
2026-05-11 7:25 ` Metzger, Markus T
2026-05-11 10:05 ` Metzger, Markus T
2026-05-12 6:36 ` Metzger, Markus T
2026-05-13 14:33 ` Tom Tromey
2026-05-13 17:05 ` Tom Tromey
2026-05-14 22:07 ` Thiago Jung Bauermann
2026-05-04 7:16 ` [PATCH] gdb, remote: fix notify debug nullptr dereference Markus Metzger
2026-05-04 15:40 ` Simon Marchi
2026-05-04 7:16 ` [PATCH] gdb, testsuite: increase timeout in gdb.threads/attach-non-stop.exp Markus Metzger
2026-05-04 15:49 ` Simon Marchi
2026-05-05 6:15 ` Metzger, Markus T
2026-05-05 15:54 ` Simon Marchi
2026-05-06 6:33 ` Metzger, Markus T
2026-05-04 7:16 ` [PATCH] gdb: update store_integer's comment Markus Metzger
2026-05-04 15:52 ` Simon Marchi
2026-05-04 7:16 ` [PATCH] gdb: use correct target in notify_thread_exited() Markus Metzger
2026-05-04 16:06 ` Simon Marchi
2026-05-05 7:56 ` Metzger, Markus T
2026-05-05 16:10 ` Simon Marchi
2026-05-06 6:56 ` Metzger, Markus T
2026-05-04 7:16 ` [PATCH v2] gdb, btrace: support libipt v2.2 events Markus Metzger
2026-05-04 12:08 ` Eli Zaretskii
2026-05-04 14:00 ` Metzger, Markus T
2026-05-04 15:04 ` Eli Zaretskii
2026-05-05 4:32 ` Metzger, Markus T
2026-05-05 5:12 ` Eli Zaretskii
2026-05-04 14:44 ` [PATCH] gdb, btrace: fix wrong #endif comments Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM8PR11MB5749F36B55336CB756E7B8ABDE3C2@DM8PR11MB5749.namprd11.prod.outlook.com \
--to=markus.t.metzger@intel.com \
--cc=gdb-patches@sourceware.org \
--cc=simark@simark.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox