[PATCH 2/2] glibc-2.34: Fix internal error when running gdb.base/gdb-sigterm.exp
Kevin Buettner
kevinb@redhat.com
Tue Jul 13 23:35:21 GMT 2021
Hi Pedro,
On Sat, 10 Jul 2021 20:07:28 +0100
Pedro Alves <pedro@palves.net> wrote:
> On 2021-07-10 3:51 a.m., Kevin Buettner via Gdb-patches wrote:
>
> > 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.
>
> This isn't right. The real bug is that inferior_ptid and current_thread_ got
> out of sync. Where did that happen? What set inferior_ptid without using
> switch_to_thread & friends?
inferior_ptid is temporarily set without changing the current thread in
ps_xfer_memory in proc-service.c:
static ps_err_e
ps_xfer_memory (const struct ps_prochandle *ph, psaddr_t addr,
gdb_byte *buf, size_t len, int write)
{
scoped_restore_current_inferior restore_inferior;
set_current_inferior (ph->thread->inf);
scoped_restore_current_program_space restore_current_progspace;
set_current_program_space (ph->thread->inf->pspace);
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = ph->thread->ptid;
CORE_ADDR core_addr = ps_addr_to_core_addr (addr);
int ret;
if (write)
ret = target_write_memory (core_addr, buf, len);
else
ret = target_read_memory (core_addr, buf, len);
return (ret == 0 ? PS_OK : PS_ERR);
}
Under normal circumstances, inferior_ptid is set and then either
target_read_memory() or target_write_memory() are called after
which it'll be reset to its former value when ps_xfer_memory
returns.
However, should GDB receive a SIGTERM while this is happening,
the QUIT processing code in target_read() will be taken, leading
to an eventual call to inferior_thread where the assert occurs.
Here's the relevant portion of the backtrace on my F34 w/ glibc-2.33.9000
machine:
#18 0x0000000000b6abf2 in internal_error (file=<optimized out>,
line=<optimized out>, fmt=<optimized out>)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdbsupport/errors.cc:55
#19 0x00000000009b72e2 in inferior_thread ()
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/thread.c:72
#20 0x00000000009b8b2b in any_thread_of_inferior (inf=0x1603a60)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/thread.c:642
#21 0x00000000009c45b8 in kill_or_detach (inf=0x1603a60, from_tty=0)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/top.c:1677
#22 0x00000000009c49e7 in quit_force (exit_arg=0x0, from_tty=0)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/top.c:1779
#23 0x0000000000a37e57 in quit ()
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/utils.c:629
#24 0x0000000000a37eb3 in maybe_quit ()
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/utils.c:653
#25 0x000000000099d8ef in target_read (ops=0x108b9c0 <the_thread_db_target>,
object=TARGET_OBJECT_MEMORY, annex=0x0, buf=0x7ffca2d41d90 "",
offset=140737354129392, len=8)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/target.c:2025
#26 0x000000000099d2e6 in target_read_memory (memaddr=0x7ffff7ffdff0,
myaddr=0x7ffca2d41d90 "", len=8)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/target.c:1810
#27 0x0000000000854fa0 in ps_xfer_memory (During symbol reading: const value length mismatch for 'sigall_set', got 128, expected 0
ph=0x1b086d8, addr=0x7ffff7ffdff0,
buf=0x7ffca2d41d90 "", len=8, write=0)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/proc-service.c:90
#28 0x0000000000855160 in ps_pdread (ph=0x1b086d8, addr=0x7ffff7ffdff0,
buf=0x7ffca2d41d90, size=8)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/proc-service.c:124
#29 0x00007fc1240151f0 in _td_fetch_value (ta=ta@entry=0x1b08740,
desc=desc@entry=0x1b087f0, descriptor_name=descriptor_name@entry=14,
idx=idx@entry=0x0, address=<optimized out>,
result=result@entry=0x7ffca2d41dc0) at fetch-value.c:115
#30 0x00007fc124011bdd in td_ta_map_lwp2thr (ta_arg=0x1b08740, lwpid=1452077,
th=0x7ffca2d41f90) at td_ta_map_lwp2thr.c:194
#31 0x00000000007ab627 in thread_from_lwp (stopped=0x18588b0, ptid=...)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/linux-thread-db.c:416
#32 0x00000000007ada46 in thread_db_target::wait (
this=0x108b9c0 <the_thread_db_target>, ptid=..., ourstatus=0x7ffca2d42578,
options=...)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/linux-thread-db.c:1431
#33 0x000000000099e953 in target_wait (ptid=..., status=0x7ffca2d42578,
options=...)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/target.c:2608
#34 0x0000000000756eaa in do_target_wait_1 (inf=0x1603a60, ptid=...,
status=0x7ffca2d42578, options=...)
at /ironwood1/sourceware-git/f34-2-glibc234/bld/../../worktree-glibc234/gdb/infrun.c:3663
The key points are as follows:
1) inferior_ptid and current_thread_ are set to null_ptid and nullptr
respectively via the call to switch_to_inferior_no_thread() in
do_target_wait_1().
2) Later on, while attempting to figure out the thread corresponding to an
LWP, ps_xfer_memory is called().
3) inferior_ptid is set (without also setting current_thread_) within
ps_xfer_memory(). Arrangements are made, however, to have
inferior_ptid's value restored upon return from ps_xfer_memory().
4) Lower level memory xfer functions are invoked from ps_xfer_memory().
5) A SIGTERM is delivered to GDB; the signal handler is invoked causing
sync_quit_force_run to be set.
6) The QUIT processing code in target_read_memory notices that sync_quit_force_run
is set. It calls quit() which calls quit_force() which calls kill_or_detach().
7) Mayhem (well, an assert) occurs due to inferior_ptid being something other than
null_ptid while current_thread_ is still nullptr.
Kevin
More information about the Gdb-patches
mailing list