golang/go

runtime: don't spawn threads from locked Ms

aclements opened this issue · 4 comments

Currently the runtime can spawn a new OS thread from essentially any M. This is bad if it attempts to spawn from a locked M that's locked because the goroutine on that M put the OS thread into a strange state. The new thread will inherit this state and start running other goroutines.

For example, this blog post describes the effects of this when trying to manipulate Linux namespaces from within a goroutine: https://www.weave.works/blog/linux-namespaces-and-go-don-t-mix

We should instead make sure we never spawn new threads from locked Ms. If we need to start a new thread while running on a locked M, we should forward the clone operation to a known-clean thread. We could either keep around a thread specifically for this purpose, or use the existing sysmon thread.

This is related to #20395, which is the other way a tainted thread can wind up back in the runtime's thread pool.

CL https://golang.org/cl/46033 mentions this issue.

cc @LK4D4 just figured you would be curious

This is related to #13164, which was solved a different way.

Looks like the proposed solution has the same idea, just using an entire spare thread as the "known good" state instead of just initSigmask, which is likely to be redundant after this fix goes in. (Because ensureSigM calls LockOSThread already.)

wsc1 commented

Just wanted to note this related message on golang-dev, as the notion of "clean thread" may be manipulated anyway via scheduling inheritance via pthread_attr or chrt linux and the like. Seems to me like a necessary and useful feature to isolate thread properties from threads created via package "C", but not via the OS.