From: Kevin Buettner via Gdb-patches <gdb-patches@sourceware.org>
To: gdb-patches@sourceware.org
Subject: [PATCH 2/2] glibc-2.34: Fix internal error when running gdb.base/gdb-sigterm.exp
Date: Fri, 9 Jul 2021 22:51:29 -0400 [thread overview]
Message-ID: <20210710025129.201884-3-kevinb@redhat.com> (raw)
In-Reply-To: <20210710025129.201884-1-kevinb@redhat.com>
This commit fixes an internal error that occurs when running
gdb.base/gdb-sigterm.exp on a machine with a prerelease of glibc-2.34.
This test case, gdb.base/gdb-sigterm.exp, turns on infrun debugging
(via "set debug infrun 1") and then attempts to do a step at the
source line "for (;;);" Of course, this is an infinite loop, so
there's no way to get to the next line. When run by hand, GDB busily
prints out the infrun debugging log messages without end. After a
while, a SIGTERM is sent from an external source - when debugging by
hand, I'm sending it from another terminal, but when running the test,
the test case sends a SIGTERM shortly after one of the infrun debug
messages is seen. Regardless, GDB is expected to shut down cleanly.
The test is run 50 times; if it shuts down cleanly after 50
iterations, the test passes; otherwise it's supposed to fail.
When running the test by hand, I'm doing:
file testsuite/outputs/gdb.base/gdb-sigterm/gdb-sigterm
set height 0
set width 0
b main
run
tbreak 29
continue
set range-stepping off
set debug infrun 1
step
At this point, GDB will start generating copious amounts of log
output. I then send a SIGTERM to the gdb process from another
terminal.
The internal error occurs roughly once in every five tries. The
backtrace shows that a double internal error occurs - GDB detects
this recursion and bails out on the second one. The first internal
error is caused by the assert in inferior_thread() in thread.c.
Further up the stack, I see:
#34 0x0000000000756eaa in do_target_wait_1 (inf=0x1603a60, ptid=...,
status=0x7ffca2d42578, options=...)
at worktree-glibc234/gdb/infrun.c:3663
It's calling target_wait() at this point; there is a call chain
eventually leading to inferior_thread() where the assert occurs. One
of the interesting things is that the call chain goes through the QUIT
mechanism (i.e. a call to maybe_quit()) in target_read(). If global
sync_quit_force_run is non-zero - which will be the case after GDB
receives a SIGTERM signal - the path through various calls is taken
eventually culiminating in the assert / internal error.
Now for the important bit: At the beginning of do_target_wait_1()
is the following code:
/* We know that we are looking for an event in the target of inferior
INF, but we don't know which thread the event might come from. As
such we want to make sure that INFERIOR_PTID is reset so that none of
the wait code relies on it - doing so is always a mistake. */
switch_to_inferior_no_thread (inf);
This call causes the variable being tested by the assert to be
NULL (actually nullptr) which ultimately triggers the assert.
So... it does seem that setting the variable in question
(current_thread_) to nullptr is intentional, but that path to the
triggered assert was not anticipated.
The reason that the problem occurs with glibc-2.34 is that
libthread_db will always be loaded now; thus the wait() machinery
found in linux-thread-db.c is used instead of linux_nat_target::wait
(which is found in linux-nat.c).
gdb/ChangeLog:
* thread.c (any_thread_of_inferior): Don't call inferior_thread()
when there is no current thread.
---
gdb/thread.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/gdb/thread.c b/gdb/thread.c
index f850f05ad48..3fe81e810c0 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -638,7 +638,8 @@ any_thread_of_inferior (inferior *inf)
gdb_assert (inf->pid != 0);
/* Prefer the current thread, if there's one. */
- if (inf == current_inferior () && inferior_ptid != null_ptid)
+ if (inf == current_inferior () && inferior_ptid != null_ptid
+ && !is_current_thread (nullptr))
return inferior_thread ();
for (thread_info *tp : inf->non_exited_threads ())
--
2.32.0
next prev parent reply other threads:[~2021-07-10 2:53 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-10 2:51 [PATCH 0/2] glibc-2.34: Fix gdb.base/gdb-sigterm.exp failure/error Kevin Buettner via Gdb-patches
2021-07-10 2:51 ` [PATCH 1/2] Handle recursive internal problem in gdb_internal_error_resync Kevin Buettner via Gdb-patches
2021-07-10 2:51 ` Kevin Buettner via Gdb-patches [this message]
2021-07-10 19:07 ` [PATCH 2/2] glibc-2.34: Fix internal error when running gdb.base/gdb-sigterm.exp Pedro Alves
2021-07-13 23:35 ` Kevin Buettner via Gdb-patches
2021-07-14 0:07 ` Pedro Alves
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=20210710025129.201884-3-kevinb@redhat.com \
--to=gdb-patches@sourceware.org \
--cc=kevinb@redhat.com \
/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