runtime: avoid CreateThread panic when exiting process

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>
This commit is contained in:
Austin Clements 2016-12-20 15:37:56 -05:00
parent c44da14440
commit f24384f686

View 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")
}