Skip to content

Commit d04dcd4

Browse files
committed
Support all as parameter in gdb goroutine commands.
For example, can use `goroutine all bt` to dump all goroutines' infomation.
1 parent 049c8db commit d04dcd4

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

doc/debugging_with_gdb.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ <h3 id="Go_Extensions">Go Extensions</h3>
149149
(gdb) <b>help goroutine</b></pre>
150150
For example:
151151
<pre>(gdb) <b>goroutine 12 bt</b></pre>
152+
You can inspect all goroutines by passing <code>all</code> instead of a specific goroutine's ID.
153+
For example:
154+
<pre>(gdb) <b>goroutine all bt</b></pre>
152155
</li>
153156
</ul>
154157

src/runtime/runtime-gdb.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,10 @@ class GoroutineCmd(gdb.Command):
511511
512512
Usage: (gdb) goroutine <goid> <gdbcmd>
513513
514+
You could pass "all" as <goid> to apply <gdbcmd> to all goroutines.
515+
516+
For example: (gdb) goroutine all <gdbcmd>
517+
514518
Note that it is ill-defined to modify state in the context of a goroutine.
515519
Restrict yourself to inspecting values.
516520
"""
@@ -519,9 +523,20 @@ def __init__(self):
519523
gdb.Command.__init__(self, "goroutine", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)
520524

521525
def invoke(self, arg, _from_tty):
522-
goid, cmd = arg.split(None, 1)
523-
goid = gdb.parse_and_eval(goid)
524-
pc, sp = find_goroutine(int(goid))
526+
goid_str, cmd = arg.split(None, 1)
527+
goids = []
528+
529+
if goid_str == 'all':
530+
for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
531+
goids.append(int(ptr['goid']))
532+
else:
533+
goids = [int(gdb.parse_and_eval(goid_str))]
534+
535+
for goid in goids:
536+
self.invoke_per_goid(goid, cmd)
537+
538+
def invoke_per_goid(self, goid, cmd):
539+
pc, sp = find_goroutine(goid)
525540
if not pc:
526541
print("No such goroutine: ", goid)
527542
return

src/runtime/runtime-gdb_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ func testGdbPython(t *testing.T, cgo bool) {
217217
"-ex", "echo BEGIN goroutine 2 bt\n",
218218
"-ex", "goroutine 2 bt",
219219
"-ex", "echo END\n",
220+
"-ex", "echo BEGIN goroutine all bt\n",
221+
"-ex", "goroutine all bt",
222+
"-ex", "echo END\n",
220223
"-ex", "clear main.go:15", // clear the previous break point
221224
"-ex", fmt.Sprintf("br main.go:%d", nLines), // new break point at the end of main
222225
"-ex", "c",
@@ -303,6 +306,10 @@ func testGdbPython(t *testing.T, cgo bool) {
303306
t.Fatalf("goroutine 2 bt failed: %s", bl)
304307
}
305308

309+
if bl := blocks["goroutine all bt"]; !btGoroutine1Re.MatchString(bl) || !btGoroutine2Re.MatchString(bl) {
310+
t.Fatalf("goroutine all bt failed: %s", bl)
311+
}
312+
306313
btGoroutine1AtTheEndRe := regexp.MustCompile(`(?m)^#0\s+(0x[0-9a-f]+\s+in\s+)?main\.main.+at`)
307314
if bl := blocks["goroutine 1 bt at the end"]; !btGoroutine1AtTheEndRe.MatchString(bl) {
308315
t.Fatalf("goroutine 1 bt at the end failed: %s", bl)

0 commit comments

Comments
 (0)