1
0
mirror of https://github.com/golang/go synced 2024-11-26 03:47:57 -07:00

runtime: free Windows event handles after last lock is dropped

Calls to lock may need to use global members of mOS that also need to be
cleaned up before the thread exits. Before this commit, these resources
would leak. Moving them to be cleaned up in unminit, however, would race
with gstack on unix. So this creates a new helper, mdestroy, to release
resources that must be destroyed only after locks are no longer
required. We also move highResTimer lifetime to the same semantics,
since it doesn't help to constantly acquire and release the timer object
during dropm.

Updates #43720.

Change-Id: Ib3f598f3fda1b2bbcb608099616fa4f85bc1c289
Reviewed-on: https://go-review.googlesource.com/c/go/+/284137
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2021-01-15 13:01:37 +01:00
parent 5a8fbb0d2d
commit dbab079835
12 changed files with 80 additions and 12 deletions

View File

@ -227,6 +227,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
func sigtramp()
//go:nosplit

View File

@ -180,6 +180,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
// tstart is a function descriptor to _tstart defined in assembly.
var tstart funcDescriptor

View File

@ -325,6 +325,11 @@ func unminit() {
}
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
//go:nosplit
func osyield() {
usleep(1)

View File

@ -203,6 +203,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
func sigtramp()
type sigactiont struct {

View File

@ -319,6 +319,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
func sigtramp()
type sigactiont struct {

View File

@ -84,6 +84,11 @@ func minit() {
func unminit() {
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
func osinit() {
ncpu = 1
getg().m.procid = 2

View File

@ -375,6 +375,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
//#ifdef GOARCH_386
//#define sa_handler k_sa_handler
//#endif

View File

@ -290,6 +290,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
func sigtramp()
type sigactiont struct {

View File

@ -257,6 +257,11 @@ func unminit() {
unminitSignals()
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
func sigtramp()
type sigactiont struct {

View File

@ -213,6 +213,11 @@ func minit() {
func unminit() {
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func mdestroy(mp *m) {
}
var sysstat = []byte("/dev/sysstat\x00")
func getproccount() int32 {

View File

@ -898,20 +898,18 @@ func minit() {
throw("runtime.minit: duplicatehandle failed")
}
mp := getg().m
lock(&mp.threadLock)
mp.thread = thandle
// Configure usleep timer, if possible.
var timer uintptr
if haveHighResTimer {
timer = createHighResTimer()
if timer == 0 {
if mp.highResTimer == 0 && haveHighResTimer {
mp.highResTimer = createHighResTimer()
if mp.highResTimer == 0 {
print("runtime: CreateWaitableTimerEx failed; errno=", getlasterror(), "\n")
throw("CreateWaitableTimerEx when creating timer failed")
}
}
mp := getg().m
lock(&mp.threadLock)
mp.thread = thandle
mp.highResTimer = timer
unlock(&mp.threadLock)
// Query the true stack base from the OS. Currently we're
@ -947,13 +945,29 @@ func minit() {
func unminit() {
mp := getg().m
lock(&mp.threadLock)
stdcall1(_CloseHandle, mp.thread)
mp.thread = 0
if mp.thread != 0 {
stdcall1(_CloseHandle, mp.thread)
mp.thread = 0
}
unlock(&mp.threadLock)
}
// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
//go:nosplit
func mdestroy(mp *m) {
if mp.highResTimer != 0 {
stdcall1(_CloseHandle, mp.highResTimer)
mp.highResTimer = 0
}
unlock(&mp.threadLock)
if mp.waitsema != 0 {
stdcall1(_CloseHandle, mp.waitsema)
mp.waitsema = 0
}
if mp.resumesema != 0 {
stdcall1(_CloseHandle, mp.resumesema)
mp.resumesema = 0
}
}
// Calling stdcall on os stack.

View File

@ -1407,6 +1407,10 @@ found:
}
}
// Destroy all allocated resources. After this is called, we may no
// longer take any locks.
mdestroy(m)
if osStack {
// Return from mstart and let the system thread
// library free the g0 stack and terminate the thread.