You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
profileLoop partially synchronizes with unminit via mp.threadLock, but it drops threadLock prior to _SuspendThread and profilem.
Thus profiling may race with dropm, resulting in profilem running on an "extra" M which is no longer in use by Go and whose previous thread is running C code.
In theory, this should result in gFromSP returning nil (as logically there should not be a G at all since this isn't a Go thread), which may make sigprof crash, as it assumes gp != nil. However, in practice the SP likely still falls in the mp.g0 stack range and things end up not crashing, though with a non-meaningful profile sample.
I've been able to easily detect this condition in practice with a C thread repeatedly calling a Go function and profilem checking if mp.thread is still set.
It looks like preemptM has a similar issue. It synchronizes with "external code" using mp.preemptExtLock, which is set by cgocall, but is not set by dropm/unminit. Like profileLoop, preemptM does not fully synchronize with unminit via mp.threadLock. As a result, I believe that preemptM could attempt to preempt a C thread after unminit, which may call ExitProcess.
I think 4 is a good idea, for preemption. Not sure about profiling, maybe we could do 3. Maybe we put setting/unsetting stack bounds in the same lock. Or we could re-check mp.thread after the thread is suspended? (is there any ABA problem?)
Not sure about the implication of suspending thread with the lock held. I haven't thought it carefully, but it sounds a bit dangerous (for deadlock). Maybe it is fine.