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 <bradfitz@tailscale.com>
pull/8429/head
Brad Fitzpatrick 1 year ago committed by Brad Fitzpatrick
parent fbacc0bd39
commit 7c1068b7ac

@ -20,7 +20,7 @@ func dumpGoroutinesToURL(c *http.Client, targetURL string) {
zbuf := new(bytes.Buffer) zbuf := new(bytes.Buffer)
zw := gzip.NewWriter(zbuf) zw := gzip.NewWriter(zbuf)
zw.Write(goroutines.ScrubbedGoroutineDump()) zw.Write(goroutines.ScrubbedGoroutineDump(true))
zw.Close() zw.Close()
req, err := http.NewRequestWithContext(ctx, "PUT", targetURL, zbuf) req, err := http.NewRequestWithContext(ctx, "PUT", targetURL, zbuf)

@ -49,7 +49,7 @@ func (b *LocalBackend) handleC2N(w http.ResponseWriter, r *http.Request) {
} }
case "/debug/goroutines": case "/debug/goroutines":
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
w.Write(goroutines.ScrubbedGoroutineDump()) w.Write(goroutines.ScrubbedGoroutineDump(true))
case "/debug/prefs": case "/debug/prefs":
writeJSON(b.Prefs()) writeJSON(b.Prefs())
case "/debug/metrics": case "/debug/metrics":

@ -11,15 +11,16 @@ import (
"strconv" "strconv"
) )
// ScrubbedGoroutineDump returns the list of all current goroutines, but with the actual // ScrubbedGoroutineDump returns either the current goroutine's stack or all
// values of arguments scrubbed out, lest it contain some private key material. // goroutines' stacks, but with the actual values of arguments scrubbed out,
func ScrubbedGoroutineDump() []byte { // lest it contain some private key material.
func ScrubbedGoroutineDump(all bool) []byte {
var buf []byte var buf []byte
// Grab stacks multiple times into increasingly larger buffer sizes // Grab stacks multiple times into increasingly larger buffer sizes
// to minimize the risk that we blow past our iOS memory limit. // to minimize the risk that we blow past our iOS memory limit.
for size := 1 << 10; size <= 1<<20; size += 1 << 10 { for size := 1 << 10; size <= 1<<20; size += 1 << 10 {
buf = make([]byte, size) buf = make([]byte, size)
buf = buf[:runtime.Stack(buf, true)] buf = buf[:runtime.Stack(buf, all)]
if len(buf) < size { if len(buf) < size {
// It fit. // It fit.
break break

@ -6,7 +6,7 @@ package goroutines
import "testing" import "testing"
func TestScrubbedGoroutineDump(t *testing.T) { 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) { func TestScrubHex(t *testing.T) {

Loading…
Cancel
Save