]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: avoid CreateThread panic when exiting process
authorAustin Clements <austin@google.com>
Tue, 20 Dec 2016 20:37:56 +0000 (15:37 -0500)
committerAustin Clements <austin@google.com>
Wed, 21 Dec 2016 16:39:01 +0000 (16:39 +0000)
On Windows, CreateThread occasionally fails with ERROR_ACCESS_DENIED.
We're not sure why this is, but the Wine source code suggests that
this can happen when there's a concurrent CreateThread and ExitProcess
in the same process.

Fix this by setting a flag right before calling ExitProcess and
halting if CreateThread fails and this flag is set.

Updates #18253 (might fix it, but we're not sure this is the issue and
can't reproduce it on demand).

Change-Id: I1945b989e73a16cf28a35bf2613ffab07577ed4e
Reviewed-on: https://go-review.googlesource.com/34616
TryBot-Result: Gobot Gobot <gobot@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/os_windows.go

index 10cab90d473a22c6e9cb480c0eeb41bb0dc32229..75b8acdceb9d98e6b8325092914fbc70d9784eb4 100644 (file)
@@ -332,8 +332,12 @@ func goenvs() {
        stdcall1(_FreeEnvironmentStringsW, uintptr(strings))
 }
 
+// exiting is set to non-zero when the process is exiting.
+var exiting uint32
+
 //go:nosplit
 func exit(code int32) {
+       atomic.Store(&exiting, 1)
        stdcall1(_ExitProcess, uintptr(code))
 }
 
@@ -519,6 +523,14 @@ func newosproc(mp *m, stk unsafe.Pointer) {
                _STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
 
        if thandle == 0 {
+               if atomic.Load(&exiting) != 0 {
+                       // CreateThread may fail if called
+                       // concurrently with ExitProcess. If this
+                       // happens, just freeze this thread and let
+                       // the process exit. See issue #18253.
+                       lock(&deadlock)
+                       lock(&deadlock)
+               }
                print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n")
                throw("runtime.newosproc")
        }