From 7c1068b7acba66e3e5755a0b6c9866283bc46cd3 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 23 Jun 2023 12:43:55 -0700 Subject: [PATCH] util/goroutines: let ScrubbedGoroutineDump get only current stack ScrubbedGoroutineDump previously only returned the stacks of all goroutines. I also want to be able to use this for only the current goroutine's stack. Add a bool param to support both ways. Updates tailscale/corp#5149 Signed-off-by: Brad Fitzpatrick --- control/controlclient/debug.go | 2 +- ipn/ipnlocal/c2n.go | 2 +- util/goroutines/goroutines.go | 9 +++++---- util/goroutines/goroutines_test.go | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/control/controlclient/debug.go b/control/controlclient/debug.go index 288abfab4..0b77d8ecd 100644 --- a/control/controlclient/debug.go +++ b/control/controlclient/debug.go @@ -20,7 +20,7 @@ func dumpGoroutinesToURL(c *http.Client, targetURL string) { zbuf := new(bytes.Buffer) zw := gzip.NewWriter(zbuf) - zw.Write(goroutines.ScrubbedGoroutineDump()) + zw.Write(goroutines.ScrubbedGoroutineDump(true)) zw.Close() req, err := http.NewRequestWithContext(ctx, "PUT", targetURL, zbuf) diff --git a/ipn/ipnlocal/c2n.go b/ipn/ipnlocal/c2n.go index 54428d38e..9bbefa44f 100644 --- a/ipn/ipnlocal/c2n.go +++ b/ipn/ipnlocal/c2n.go @@ -49,7 +49,7 @@ func (b *LocalBackend) handleC2N(w http.ResponseWriter, r *http.Request) { } case "/debug/goroutines": w.Header().Set("Content-Type", "text/plain") - w.Write(goroutines.ScrubbedGoroutineDump()) + w.Write(goroutines.ScrubbedGoroutineDump(true)) case "/debug/prefs": writeJSON(b.Prefs()) case "/debug/metrics": diff --git a/util/goroutines/goroutines.go b/util/goroutines/goroutines.go index 7ca7dc660..9758b0758 100644 --- a/util/goroutines/goroutines.go +++ b/util/goroutines/goroutines.go @@ -11,15 +11,16 @@ import ( "strconv" ) -// ScrubbedGoroutineDump returns the list of all current goroutines, but with the actual -// values of arguments scrubbed out, lest it contain some private key material. -func ScrubbedGoroutineDump() []byte { +// ScrubbedGoroutineDump returns either the current goroutine's stack or all +// goroutines' stacks, but with the actual values of arguments scrubbed out, +// lest it contain some private key material. +func ScrubbedGoroutineDump(all bool) []byte { var buf []byte // Grab stacks multiple times into increasingly larger buffer sizes // to minimize the risk that we blow past our iOS memory limit. for size := 1 << 10; size <= 1<<20; size += 1 << 10 { buf = make([]byte, size) - buf = buf[:runtime.Stack(buf, true)] + buf = buf[:runtime.Stack(buf, all)] if len(buf) < size { // It fit. break diff --git a/util/goroutines/goroutines_test.go b/util/goroutines/goroutines_test.go index 24e5d36c9..ae17c399c 100644 --- a/util/goroutines/goroutines_test.go +++ b/util/goroutines/goroutines_test.go @@ -6,7 +6,7 @@ package goroutines import "testing" func TestScrubbedGoroutineDump(t *testing.T) { - t.Logf("Got:\n%s\n", ScrubbedGoroutineDump()) + t.Logf("Got:\n%s\n", ScrubbedGoroutineDump(true)) } func TestScrubHex(t *testing.T) {