diff options
| author | Damien Neil <dneil@google.com> | 2025-06-05 14:21:47 -0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-06-09 10:58:51 -0700 |
| commit | 848a768ba76d7c386c2aa4f05bc2e9e51b5948b9 (patch) | |
| tree | 91fec1f41cd6b322f1392c13629616f396260dfe | |
| parent | 049a5e603634dfdbc73b4255c7e72eabc3922d5b (diff) | |
| download | go-848a768ba76d7c386c2aa4f05bc2e9e51b5948b9.tar.xz | |
runtime: clarify stack traces for bubbled goroutines
Use the synctest bubble ID to identify bubbles in traces,
rather than the goroutine ID of the bubble's root goroutine.
Some waitReasons include a "(synctest)" suffix to distinguish
a durably blocking state from a non-durable one. For example,
"chan send" vs. "chan send (synctest)". Change this suffix
to "(durable)".
Always print a "(durable)" sufix for the state of durably
blocked bubbled goroutines. For example, print "sleep (durable)".
Drop the "[not] durably blocked" text from goroutine states,
since this is now entirely redundant with the waitReason.
Old:
goroutine 8 [chan receive (synctest), synctest bubble 7, durably blocked]:
goroutine 9 [select (no cases), synctest bubble 7, durably blocked]:
New:
goroutine 8 [chan receive (durable), synctest bubble 1]:
goroutine 9 [select (no cases) (durable), synctest bubble 1]:
Change-Id: I89112efb25150a98a2954f54d1910ccec52a5824
Reviewed-on: https://go-review.googlesource.com/c/go/+/679376
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
| -rw-r--r-- | src/runtime/runtime2.go | 28 | ||||
| -rw-r--r-- | src/runtime/traceback.go | 13 |
2 files changed, 22 insertions, 19 deletions
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 589642efc6..d1b31be172 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -1093,10 +1093,10 @@ const ( waitReasonGCWeakToStrongWait // "GC weak to strong wait" waitReasonSynctestRun // "synctest.Run" waitReasonSynctestWait // "synctest.Wait" - waitReasonSynctestChanReceive // "chan receive (synctest)" - waitReasonSynctestChanSend // "chan send (synctest)" - waitReasonSynctestSelect // "select (synctest)" - waitReasonSynctestWaitGroupWait // "sync.WaitGroup.Wait (synctest)" + waitReasonSynctestChanReceive // "chan receive (durable)" + waitReasonSynctestChanSend // "chan send (durable)" + waitReasonSynctestSelect // "select (durable)" + waitReasonSynctestWaitGroupWait // "sync.WaitGroup.Wait (durable)" waitReasonCleanupWait // "cleanup wait" ) @@ -1143,10 +1143,10 @@ var waitReasonStrings = [...]string{ waitReasonGCWeakToStrongWait: "GC weak to strong wait", waitReasonSynctestRun: "synctest.Run", waitReasonSynctestWait: "synctest.Wait", - waitReasonSynctestChanReceive: "chan receive (synctest)", - waitReasonSynctestChanSend: "chan send (synctest)", - waitReasonSynctestSelect: "select (synctest)", - waitReasonSynctestWaitGroupWait: "sync.WaitGroup.Wait (synctest)", + waitReasonSynctestChanReceive: "chan receive (durable)", + waitReasonSynctestChanSend: "chan send (durable)", + waitReasonSynctestSelect: "select (durable)", + waitReasonSynctestWaitGroupWait: "sync.WaitGroup.Wait (durable)", waitReasonCleanupWait: "cleanup wait", } @@ -1207,12 +1207,12 @@ var isIdleInSynctest = [len(waitReasonStrings)]bool{ } var ( - allm *m - gomaxprocs int32 - numCPUStartup int32 - forcegc forcegcstate - sched schedt - newprocs int32 + allm *m + gomaxprocs int32 + numCPUStartup int32 + forcegc forcegcstate + sched schedt + newprocs int32 ) var ( diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index b3baa3b4ed..00c0f08e55 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -1248,6 +1248,13 @@ func goroutineheader(gp *g) { if isScan { print(" (scan)") } + if bubble := gp.bubble; bubble != nil && + gp.waitreason.isIdleInSynctest() && + !stringslite.HasSuffix(status, "(durable)") { + // If this isn't a status where the name includes a (durable) + // suffix to distinguish it from the non-durable form, add it here. + print(" (durable)") + } if waitfor >= 1 { print(", ", waitfor, " minutes") } @@ -1255,11 +1262,7 @@ func goroutineheader(gp *g) { print(", locked to thread") } if bubble := gp.bubble; bubble != nil { - print(", synctest bubble ", bubble.root.goid, ", ") - if !gp.waitreason.isIdleInSynctest() { - print("not ") - } - print("durably blocked") + print(", synctest bubble ", bubble.id) } print("]:\n") } |
