From d04dcd4f581f97e35ee45969a864f1270d79e49b Mon Sep 17 00:00:00 2001 From: Haosdent Huang Date: Mon, 9 Jul 2018 11:55:10 +0800 Subject: [PATCH] Support all as parameter in gdb goroutine commands. For example, can use `goroutine all bt` to dump all goroutines' infomation. --- doc/debugging_with_gdb.html | 3 +++ src/runtime/runtime-gdb.py | 21 ++++++++++++++++++--- src/runtime/runtime-gdb_test.go | 7 +++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html index 3899ac92d50823..36ec0bdf376cb5 100644 --- a/doc/debugging_with_gdb.html +++ b/doc/debugging_with_gdb.html @@ -149,6 +149,9 @@

Go Extensions

(gdb) help goroutine For example:
(gdb) goroutine 12 bt
+You can inspect all goroutines by passing all instead of a specific goroutine's ID. +For example: +
(gdb) goroutine all bt
diff --git a/src/runtime/runtime-gdb.py b/src/runtime/runtime-gdb.py index 72645d289e646d..6139f994853b9e 100644 --- a/src/runtime/runtime-gdb.py +++ b/src/runtime/runtime-gdb.py @@ -511,6 +511,10 @@ class GoroutineCmd(gdb.Command): Usage: (gdb) goroutine + You could pass "all" as to apply to all goroutines. + + For example: (gdb) goroutine all + Note that it is ill-defined to modify state in the context of a goroutine. Restrict yourself to inspecting values. """ @@ -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 diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go index 63d6e52dea3549..de1bac65daf7fc 100644 --- a/src/runtime/runtime-gdb_test.go +++ b/src/runtime/runtime-gdb_test.go @@ -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", @@ -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)