From: "Alexandra Hájková" <ahajkova@redhat.com>
To: gdb-patches@sourceware.org
Cc: ezulian@redhat.com
Subject: [PATCH] Add drg_why_sleeping.py
Date: Mon, 31 Aug 2026 22:54:54 +0200 [thread overview]
Message-ID: <20260831205514.1987454-2-ahajkova@redhat.com> (raw)
In-Reply-To: <20260831205514.1987454-1-ahajkova@redhat.com>
---
.../lib/gdb/command/drgn_why_sleeping.py | 72 ++++++++++++++++++
sleep_test.c | 76 +++++++++++++++++++
2 files changed, 148 insertions(+)
create mode 100644 gdb/python/lib/gdb/command/drgn_why_sleeping.py
create mode 100644 sleep_test.c
diff --git a/gdb/python/lib/gdb/command/drgn_why_sleeping.py b/gdb/python/lib/gdb/command/drgn_why_sleeping.py
new file mode 100644
index 00000000000..ea11a73faae
--- /dev/null
+++ b/gdb/python/lib/gdb/command/drgn_why_sleeping.py
@@ -0,0 +1,72 @@
+# GDB 'drgn_why_sleeping' command.
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Implementation of the GDB 'drgn_why_sleeping' command using the GDB Python API."""
+
+import gdb
+import drgn
+from drgn.helpers.linux.pid import find_task
+from drgn.helpers.linux.sched import task_state_to_char
+
+class DrgnWhySleeping(gdb.Command):
+ """Look at kernel stack and show what is the thread blocked at.
+
+ Usage: Run GDB as root to be able to read from /proc/kcore.
+ The command needs debugging symbols for the running kernel.
+ (gdb) source ~/binutils-gdb/gdb/python/lib/gdb/command/drgn_why_sleeping.py
+ (gdb) info threads
+ (gdb) thread n
+ (gdb) drgn_why_sleeping
+ """
+
+ def __init__(self):
+ super(DrgnWhySleeping, self).__init__(
+ name="drgn_why_sleeping", command_class=gdb.COMMAND_STATUS, prefix=False
+ )
+
+ def invoke(self, arg_str, from_tty):
+ if gdb.selected_thread() is None:
+ raise gdb.GdbError(
+ (
+ "Can't find selected thread. "
+ )
+ )
+ tid = gdb.selected_thread().ptid[1]
+
+ try:
+ prog = drgn.program_from_kernel()
+ except Exception as e:
+ raise gdb.GdbError(
+ "Can't read /proc/kcore, %s. Try running GDB as root. " % str(e)
+ )
+ task = find_task(prog, tid)
+ task_state = task_state_to_char(task)
+ stack = prog.stack_trace(task)
+ print(f"Task state: {task_state}")
+ if arg_str:
+ for frame in stack:
+ if frame.name == arg_str:
+ print(frame.name)
+ for var in frame.locals():
+ print(f" {var} = {frame[var]}")
+ break
+ else:
+ print("Frame not found: %s" % arg_str)
+ else:
+ for frame in stack:
+ print(frame.name)
+
+DrgnWhySleeping()
diff --git a/sleep_test.c b/sleep_test.c
new file mode 100644
index 00000000000..c324e55944c
--- /dev/null
+++ b/sleep_test.c
@@ -0,0 +1,76 @@
+/*
+ * sleep_test.c - reproducer for testing drgn_why_sleeping GDB command
+ *
+ * Creates three threads, each blocked in a different kind of interruptible
+ * sleep, then prints the PID and waits so GDB can attach.
+ *
+ * Compile: gcc -g -o sleep_test sleep_test.c -lpthread
+ */
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static pthread_mutex_t mutex_a = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t mutex_b = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static int pipe_fds[2];
+
+/* Blocked trying to acquire mutex_a, which main holds. */
+static void *mutex_waiter(void *arg)
+{
+ printf("[thread 1] blocking on mutex_a...\n");
+ fflush(stdout);
+ pthread_mutex_lock(&mutex_a);
+ /* never reached during the test */
+ pthread_mutex_unlock(&mutex_a);
+ return NULL;
+}
+
+/* Blocked in pthread_cond_wait; nobody will ever signal cond. */
+static void *cond_waiter(void *arg)
+{
+ pthread_mutex_lock(&mutex_b);
+ printf("[thread 2] blocking on cond...\n");
+ fflush(stdout);
+ pthread_cond_wait(&cond, &mutex_b);
+ /* never reached during the test */
+ pthread_mutex_unlock(&mutex_b);
+ return NULL;
+}
+
+/* Blocked in read(); nobody will write to the pipe. */
+static void *pipe_reader(void *arg)
+{
+ char buf[16];
+ printf("[thread 3] blocking on pipe read...\n");
+ fflush(stdout);
+ read(pipe_fds[0], buf, sizeof(buf));
+ /* never reached during the test */
+ return NULL;
+}
+
+int main(void)
+{
+ pthread_t t1, t2, t3;
+
+ pipe(pipe_fds);
+
+ /* Hold mutex_a before creating thread 1 so it blocks immediately. */
+ pthread_mutex_lock(&mutex_a);
+
+ pthread_create(&t1, NULL, mutex_waiter, NULL);
+ pthread_create(&t2, NULL, cond_waiter, NULL);
+ pthread_create(&t3, NULL, pipe_reader, NULL);
+
+ /* Give threads time to reach their blocking calls. */
+ sleep(1);
+
+ printf("\n[main] PID %d ready — attach GDB now\n", getpid());
+ fflush(stdout);
+
+ /* Block here so GDB has time to attach. */
+ pause();
+
+ return 0;
+}
--
2.52.0
next prev parent reply other threads:[~2026-08-31 20:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 20:54 [RFC PATCH 0/1] gdb/python: add drg_why_sleeping command Alexandra Hájková
2026-08-31 20:54 ` Alexandra Hájková [this message]
2026-09-01 16:52 ` [PATCH] Add drg_why_sleeping.py 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-2-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