Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: support all as parameter in gdb goroutine commands. #26283

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/debugging_with_gdb.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ <h3 id="Go_Extensions">Go Extensions</h3>
(gdb) <b>help goroutine</b></pre>
For example:
<pre>(gdb) <b>goroutine 12 bt</b></pre>
You can inspect all goroutines by passing <code>all</code> instead of a specific goroutine's ID.
For example:
<pre>(gdb) <b>goroutine all bt</b></pre>
</li>
</ul>

Expand Down
21 changes: 18 additions & 3 deletions src/runtime/runtime-gdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,10 @@ class GoroutineCmd(gdb.Command):

Usage: (gdb) goroutine <goid> <gdbcmd>

You could pass "all" as <goid> to apply <gdbcmd> to all goroutines.

For example: (gdb) goroutine all <gdbcmd>

Note that it is ill-defined to modify state in the context of a goroutine.
Restrict yourself to inspecting values.
"""
Expand All @@ -519,9 +523,20 @@ def __init__(self):
gdb.Command.__init__(self, "goroutine", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)

def invoke(self, arg, _from_tty):
goid, cmd = arg.split(None, 1)
goid = gdb.parse_and_eval(goid)
pc, sp = find_goroutine(int(goid))
goid_str, cmd = arg.split(None, 1)
goids = []

if goid_str == 'all':
for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
goids.append(int(ptr['goid']))
else:
goids = [int(gdb.parse_and_eval(goid_str))]

for goid in goids:
self.invoke_per_goid(goid, cmd)

def invoke_per_goid(self, goid, cmd):
pc, sp = find_goroutine(goid)
if not pc:
print("No such goroutine: ", goid)
return
Expand Down
7 changes: 7 additions & 0 deletions src/runtime/runtime-gdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ func testGdbPython(t *testing.T, cgo bool) {
"-ex", "echo BEGIN goroutine 2 bt\n",
"-ex", "goroutine 2 bt",
"-ex", "echo END\n",
"-ex", "echo BEGIN goroutine all bt\n",
"-ex", "goroutine all bt",
"-ex", "echo END\n",
"-ex", "clear main.go:15", // clear the previous break point
"-ex", fmt.Sprintf("br main.go:%d", nLines), // new break point at the end of main
"-ex", "c",
Expand Down Expand Up @@ -303,6 +306,10 @@ func testGdbPython(t *testing.T, cgo bool) {
t.Fatalf("goroutine 2 bt failed: %s", bl)
}

if bl := blocks["goroutine all bt"]; !btGoroutine1Re.MatchString(bl) || !btGoroutine2Re.MatchString(bl) {
t.Fatalf("goroutine all bt failed: %s", bl)
}

btGoroutine1AtTheEndRe := regexp.MustCompile(`(?m)^#0\s+(0x[0-9a-f]+\s+in\s+)?main\.main.+at`)
if bl := blocks["goroutine 1 bt at the end"]; !btGoroutine1AtTheEndRe.MatchString(bl) {
t.Fatalf("goroutine 1 bt at the end failed: %s", bl)
Expand Down