Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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


  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