From: "Alexandra Hájková" <ahajkova@redhat.com>
To: gdb-patches@sourceware.org
Cc: ezulian@redhat.com
Subject: [RFC PATCH 0/1] gdb/python: add drg_why_sleeping command
Date: Mon, 31 Aug 2026 22:54:53 +0200 [thread overview]
Message-ID: <20260831205514.1987454-1-ahajkova@redhat.com> (raw)
When using GDB to debug a multithreaded program with a thread in
interruptible sleep, we can call `info threads` command in GDB,
which shows the userspace frame each thread is stopped at.However,
GDB has no way to show why a thread is sleeping on the kernel
side—which kernel function it is blocked in, or the full
kernel call path that led there. Drgn, on the other hand, can
provide this information. Drgn does not use ptrace — it reads
/proc/kcore directly which means drgn can run alongside a GDB
session without any conflict, since GDB already holds ptrace on
the inferior.
I wrote a small GDB Python command, drgn_why_sleeping, that demonstrates
this cooperation. When invoked on a selected thread (in GDB non-stop mode, so the thread
remains in its sleep state), it retrieves the full kernel stack via drgn
When debugging a multithreaded program with GDB, `info threads` shows
the userspace frame each thread is stopped at, but GDB has no way to show
why a thread is sleeping on the kernel side -- which kernel function it is
blocked in, or the call path that led there.
To run this script drgn and kernel debug has to be installed. I'm using
to drgn's sudo helper, which opens /proc/kcore in a transient privileged
child and passes the fd back over a unix socket. GDB itself stays unprivileged.
Running GDB itsel is another possibility.
In order to make things easier, I included sleeping_test.c program as
a part of this patch since it's RFC.
To demostrate this command, sleep_test has to be compiled and run
separetely. Then we need to attach GDB in non-stop mode for example
./gdb/gdb --data-directory=gdb/data-directory -ex "set non-stop on" -p 1979281
then we need to resume the thread before inspecting it:
(gdb) info threads
(gdb) thread N
(gdb) drgn_why_sleeping
If the thread stays GDB-stopped, the kernel stack just shows ptrace_stop
and not the real reason it was sleeping. Resuming it (continue &) lets it
return to its kernel sleep.
Id Target Id Frame
2 ... "sleep_test" (LWP 1979284) 0x... in read () from libc.so.6
...
(gdb) thread 2
Running before resuming the thread which means GDB still has it ptrace-stopped,
so the kernel stack only shows the ptrace stop, not the real sleep:
(gdb) drgn_why_sleeping
Task state: t
context_switch
__schedule
schedule
ptrace_stop
ptrace_signal
get_signal
...
do_syscall_64
entry_SYSCALL_64
After resuming just this thread (non-stop) so it re-enters its sleep,
and running the drgn_why_sleep again we're seeing the real reason it
is blocked:
(gdb) continue &
(gdb) drgn_why_sleeping
Task state: S
context_switch
__schedule
schedule
anon_pipe_read
new_sync_read
vfs_read
ksys_read
do_syscall_64
entry_SYSCALL_64
Given a frame name, the command prints that frame's locals instead. Here
the file operations resolve to pipeanon_fops, confirming from the kernel
data itself that the thread is blocked on a pipe:
(gdb) drgn_why_sleeping vfs_read
Task state: S
vfs_read
file = *(struct file *)0xffff8c8a1d585600 = {
.f_op = (const struct file_operations *)pipeanon_fops+0x0 = 0x...,
.f_flags = (unsigned int)0,
.f_inode = (struct inode *)0xffff8c87c87a7200,
...
}
Limitations:
Secure Boot with lockdown=confidentiality) blocks /proc/kcore despite running
as root.
---
<git format-patch will append the diffstat here>
next reply other threads:[~2026-08-31 20:55 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 20:54 Alexandra Hájková [this message]
2026-08-31 20:54 ` [PATCH] Add drg_why_sleeping.py Alexandra Hájková
2026-09-01 16:52 ` Tom Tromey
2026-09-02 15:29 ` Alexandra Petlanova Hajkova
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=20260831205514.1987454-1-ahajkova@redhat.com \
--to=ahajkova@redhat.com \
--cc=ezulian@redhat.com \
--cc=gdb-patches@sourceware.org \
/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