@@ -1341,7 +1341,32 @@ func goroutineLeakProfileWithLabelsConcurrent(p []profilerecord.StackRecord, lab
13411341 // Visit each leaked goroutine and try to record its stack.
13421342 var offset int
13431343 forEachGRace (func (gp1 * g ) {
1344- if readgstatus (gp1 ) == _Gleaked {
1344+ // NOTE(vsaioc): Each goroutine leak profile request is preceded by a run of the GC
1345+ // in goroutine leak detection mode. At the beginning of the GC cycle, all previously
1346+ // reported goroutine leaks are reset to _Gwaiting. As a result, incomplete goroutine
1347+ // leak profiles may be produced if multiple goroutine leak profile requests are issued
1348+ // concurrently.
1349+ //
1350+ // Example trace:
1351+ //
1352+ // G1 | GC | G2
1353+ // ----------------------+-----------------------------+---------------------
1354+ // Request profile | . | .
1355+ // . | . | Request profile
1356+ // . | [G1] Resets leaked g status | .
1357+ // . | [G1] Leaks detected | .
1358+ // . | <New cycle> | .
1359+ // . | [G2] Resets leaked g status | .
1360+ // . | . | Write profile
1361+ // . | [G2] Leaks detected | .
1362+ // Write profile | . | .
1363+ // ----------------------+-----------------------------+---------------------
1364+ // G1 completes profile |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/| G2 misses leaks
1365+ //
1366+ // While this is a bug, normal use cases presume that goroutine leak profile
1367+ // requests are issued on a single track. Adding synchronization between over
1368+ // goroutine leak profile requests would only needlessly increase overhead.
1369+ if readgstatus (gp1 )&^_Gscan == _Gleaked {
13451370 systemstack (func () { saveg (^ uintptr (0 ), ^ uintptr (0 ), gp1 , & p [offset ], pcbuf ) })
13461371 if labels != nil {
13471372 labels [offset ] = gp1 .labels
0 commit comments