]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: support all as parameter in gdb goroutine commands.
authorHaosdent Huang <haosdent@gmail.com>
Mon, 29 Apr 2019 02:04:26 +0000 (02:04 +0000)
committerDavid Chase <drchase@google.com>
Mon, 29 Apr 2019 18:11:11 +0000 (18:11 +0000)
For example, can use `goroutine all bt` to dump all goroutines'
information.

Change-Id: I51b547c2b837913e4bdabf0f45b28f09250a3e34
GitHub-Last-Rev: d04dcd4f581f97e35ee45969a864f1270d79e49b
GitHub-Pull-Request: golang/go#26283
Reviewed-on: https://go-review.googlesource.com/c/go/+/122589
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
doc/debugging_with_gdb.html
src/runtime/runtime-gdb.py
src/runtime/runtime-gdb_test.go

index 3899ac92d50823439977682010afb7e9868f7c2d..36ec0bdf376cb501c44fdf30d87b10b211a25e5c 100644 (file)
@@ -149,6 +149,9 @@ Inspecting goroutines:
 (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>
 
index 72645d289e646df4f80afdfe73c0b7188e0a8559..6139f994853b9ed4a5acd291f17192fddfc324bd 100644 (file)
@@ -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.
        """
@@ -519,9 +523,20 @@ class GoroutineCmd(gdb.Command):
                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
index 63d6e52dea3549235c3652ddfdd4450264f96be7..de1bac65daf7fc15f9b6df0bd962b62be1463412 100644 (file)
@@ -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)