]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: free Windows event handles after last lock is dropped
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 15 Jan 2021 12:01:37 +0000 (13:01 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 18 Jan 2021 18:16:12 +0000 (18:16 +0000)
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>

12 files changed:
src/runtime/os3_solaris.go
src/runtime/os_aix.go
src/runtime/os_darwin.go
src/runtime/os_dragonfly.go
src/runtime/os_freebsd.go
src/runtime/os_js.go
src/runtime/os_linux.go
src/runtime/os_netbsd.go
src/runtime/os_openbsd.go
src/runtime/os_plan9.go
src/runtime/os_windows.go
src/runtime/proc.go

index d6e36fbfbbe51fa7d57ce5e4eaf39e897204d9c7..6ba11afd93ca439785d05a1e9a3d112beb1ec7a5 100644 (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
index 0c501be96a94c8366781c2f075cb9f117812d824..303f0876deb711333cda9836eb26adfd67f10cfc 100644 (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
 
index e0a43c28aaa693dce07e1ae1689a77d606f6232e..9ca17c20dff02988b55cd24c9824ba775abe3a45 100644 (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)
index 6578fcbeb1f331f75b2ee15e9ed4907c77b3411e..383df54bd4322a4e6593e17c1bf2a9ac15fd1ca7 100644 (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 {
index 1c60ee2a57f4c6cabe73ee91e3614eb7703987b8..09065ccb68232df785f2d7e33abe1fca46fd3668 100644 (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 {
index 91d18a078f8b301380e780f16b61cba2bef8a004..24261e88a2060310ea155375c1e17673ebc9c9c3 100644 (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
index f122d2c2ef7c754bcb122c9affb3b7c5231e678c..058c7daf9c60d19d51545aceed41148e56f7f0c4 100644 (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
index f7f90cedc1a8b9eacd7bcd0feedd90bb1897d81a..2b742a37116ba575a28c97fbc65379a7251d8974 100644 (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 {
index d7960f4c91c9580aa9185d190bb67967609b3361..490077bc2998ca46be811ae8e49f0175c38a18cb 100644 (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 {
index a0355269373f10a7c009ec9443ecc785c9e540c3..2a84a73716078fe9fec3ea169aff505d4079f689 100644 (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 {
index 16ff285e88f4e22ed8f12dce4db0eef87c99b73d..83d0d63e5d7c5bccda0d088b8a9fb1ae8787859a 100644 (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.
index 5a942a68317ae4ee0aac5c391a31262796aa8129..b776f889364d48b44e8f9bf08627e7445355157a 100644 (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.