Currently, as a result of us releasing worldsema now to allow STW events
during a mark phase, we release worldsema between starting the world and
having the goroutine block in STW mode. This inserts preemption points
which, if followed through, could lead to a deadlock. Specifically,
because user goroutine scheduling is disabled in STW mode, the goroutine
will block before properly releasing worldsema.
The fix here is to prevent preemption while releasing the worldsema.
Fixes #38404.
Updates #19812.
Change-Id: I8ed5b3aa108ab2e4680c38e77b0584fb75690e3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/228337
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Austin Clements <austin@google.com>
// the world.
gcController.markStartTime = now
+ // In STW mode, we could block the instant systemstack
+ // returns, so make sure we're not preemptible.
+ mp = acquirem()
+
// Concurrent mark.
systemstack(func() {
now = startTheWorldWithSema(trace.enabled)
// this goroutine becomes runnable again, and we could
// self-deadlock otherwise.
semrelease(&worldsema)
+ releasem(mp)
- // In STW mode, we could block the instant systemstack
- // returns, so don't do anything important here. Make sure we
- // block rather than returning to user code.
+ // Make sure we block instead of returning to user code
+ // in STW mode.
if mode != gcBackgroundMode {
Gosched()
}