mirror of
https://github.com/golang/go.git
synced 2025-10-19 11:03:18 +00:00
runtime: don't let readTrace spin on trace.shutdown
Issue #74045 describes a scenario in which gopark is inlined into readTrace, such that there are no preemption points. This is only a problem because readTrace spins if trace.shutdown is set, through traceReaderAvailable. However, trace.shutdown is almost certainly overkill for traceReaderAvailable. The first condition, checking whether the reader gen and the flushed gen match, should be sufficient to ensure the reader wakes up and finishes flushing all buffers. The first condition is also safe because it guarantees progress. In the case of shutdown, all the trace work that will be flushed has been flushed, and so the trace reader will exit into a regular goroutine context when it's finished. If not shutting down, then the trace reader will release doneSema, increase readerGen, and then the gopark unlockf will let it block until new work actually comes in. Fixes #74045. Change-Id: Id9b15c277cb731618488771bd484577341b68675 Reviewed-on: https://go-review.googlesource.com/c/go/+/680738 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Nick Ripley <nick.ripley@datadoghq.com> Reviewed-by: Michael Pratt <mpratt@google.com> Auto-Submit: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
ea00461b17
commit
816199e421
1 changed files with 2 additions and 4 deletions
|
@ -956,7 +956,7 @@ func traceReader() *g {
|
||||||
// scheduled and should be. Callers should first check that
|
// scheduled and should be. Callers should first check that
|
||||||
// (traceEnabled() || traceShuttingDown()) is true.
|
// (traceEnabled() || traceShuttingDown()) is true.
|
||||||
func traceReaderAvailable() *g {
|
func traceReaderAvailable() *g {
|
||||||
// There are three conditions under which we definitely want to schedule
|
// There are two conditions under which we definitely want to schedule
|
||||||
// the reader:
|
// the reader:
|
||||||
// - The reader is lagging behind in finishing off the last generation.
|
// - The reader is lagging behind in finishing off the last generation.
|
||||||
// In this case, trace buffers could even be empty, but the trace
|
// In this case, trace buffers could even be empty, but the trace
|
||||||
|
@ -965,12 +965,10 @@ func traceReaderAvailable() *g {
|
||||||
// - The reader has pending work to process for it's reader generation
|
// - The reader has pending work to process for it's reader generation
|
||||||
// (assuming readerGen is not lagging behind). Note that we also want
|
// (assuming readerGen is not lagging behind). Note that we also want
|
||||||
// to be careful *not* to schedule the reader if there's no work to do.
|
// to be careful *not* to schedule the reader if there's no work to do.
|
||||||
// - The trace is shutting down. The trace stopper blocks on the reader
|
|
||||||
// to finish, much like trace advancement.
|
|
||||||
//
|
//
|
||||||
// We also want to be careful not to schedule the reader if there's no
|
// We also want to be careful not to schedule the reader if there's no
|
||||||
// reason to.
|
// reason to.
|
||||||
if trace.flushedGen.Load() == trace.readerGen.Load() || trace.workAvailable.Load() || trace.shutdown.Load() {
|
if trace.flushedGen.Load() == trace.readerGen.Load() || trace.workAvailable.Load() {
|
||||||
return trace.reader.Load()
|
return trace.reader.Load()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue