1
0
mirror of https://github.com/golang/go synced 2024-11-17 05:44:52 -07:00

runtime: hold sched.lock over traceThreadDestroy in dropm

This is required by traceThreadDestroy, though it's not strictly
necessary in this case. The requirement to hold sched.lock comes from
the assumption that traceThreadDestroy is getting called when the thread
leaves the tracer's view, but in this case the extra m that dropm is
dropping never leaves the allm list. Nevertheless, traceThreadDestroy
requires it just as a safety measure, and that's reasonable. dropm is
generally rare on pthread platforms, so the extra lock acquire over this
short critical section (and only when tracing is enabled) is fine.

Change-Id: Ib631820963c74f2f087d14a0067d0441d75d6785
Reviewed-on: https://go-review.googlesource.com/c/go/+/544396
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Michael Anthony Knyszek 2023-11-21 23:57:36 +00:00 committed by Michael Knyszek
parent 23c0d30244
commit cea35baf12

View File

@ -2428,8 +2428,20 @@ func dropm() {
// Flush all the M's buffers. This is necessary because the M might
// be used on a different thread with a different procid, so we have
// to make sure we don't write into the same buffer.
if traceEnabled() || traceShuttingDown() {
//
// N.B. traceThreadDestroy is a no-op in the old tracer, so avoid the
// unnecessary acquire/release of the lock.
if goexperiment.ExecTracer2 && (traceEnabled() || traceShuttingDown()) {
// Acquire sched.lock across thread destruction. One of the invariants of the tracer
// is that a thread cannot disappear from the tracer's view (allm or freem) without
// it noticing, so it requires that sched.lock be held over traceThreadDestroy.
//
// This isn't strictly necessary in this case, because this thread never leaves allm,
// but the critical section is short and dropm is rare on pthread platforms, so just
// take the lock and play it safe. traceThreadDestroy also asserts that the lock is held.
lock(&sched.lock)
traceThreadDestroy(mp)
unlock(&sched.lock)
}
mp.isExtraInSig = false