diff options
author | Austin Clements <austin@google.com> | 2016-12-20 15:37:56 -0500 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2016-12-21 16:39:01 +0000 |
commit | f24384f686745f95086e7f400e884a218f4456d3 (patch) | |
tree | b031b8d0de5e25f2828763f76c945a00ff26dca0 | |
parent | c44da14440e5a2e412f9b1d3f5f2f562591d8e49 (diff) | |
download | go-f24384f686745f95086e7f400e884a218f4456d3.tar.gz go-f24384f686745f95086e7f400e884a218f4456d3.zip |
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>
-rw-r--r-- | src/runtime/os_windows.go | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 10cab90d47..75b8acdceb 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -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") } |