From 65ea4c5021d44395db8728eea16eb8f7fc7420eb Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 9 Mar 2023 14:55:31 +0100 Subject: [PATCH] runtime: support GOTRACEBACK=wer on Windows GOTRACEBACK=wer is a new traceback level that acts as "crash" and also enables WER. The same effect can be achieved using debug.SetTraceback("wer"). The Go runtime currently crashes using exit(2), which bypasses WER even if it is enabled. To best way to trigger WER is calling RaiseFailFastException [1] instead, which internally launches the WER machinery. This CL also changes how GOTRACEBACK=crash crashes, so both "wer" and "crash" crash using RaiseFailFastException, which simplifies the implementation and resolves a longstanding TODO. Fixes #57441 Fixes #20498 [1] https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-raisefailfastexception Change-Id: I45669d619fbbd2f6413ce5e5f08425ed1d9aeb64 Reviewed-on: https://go-review.googlesource.com/c/go/+/474915 Reviewed-by: Davis Goodin TryBot-Result: Gopher Robot Reviewed-by: David Chase Reviewed-by: Than McIntosh Reviewed-by: Alex Brainman Run-TryBot: Quim Muntal --- src/runtime/defs_windows.go | 2 +- src/runtime/export_windows_test.go | 1 - src/runtime/extern.go | 1 + .../{relax_stub.go => nonwindows_stub.go} | 4 + src/runtime/os_windows.go | 10 ++- src/runtime/runtime1.go | 7 ++ src/runtime/signal_windows.go | 83 +++++++++++++------ src/runtime/syscall_windows_test.go | 23 +++-- 8 files changed, 95 insertions(+), 36 deletions(-) rename src/runtime/{relax_stub.go => nonwindows_stub.go} (82%) diff --git a/src/runtime/defs_windows.go b/src/runtime/defs_windows.go index 60f20a5c2c..56698fa56c 100644 --- a/src/runtime/defs_windows.go +++ b/src/runtime/defs_windows.go @@ -67,7 +67,7 @@ type exceptionrecord struct { exceptioncode uint32 exceptionflags uint32 exceptionrecord *exceptionrecord - exceptionaddress *byte + exceptionaddress uintptr numberparameters uint32 exceptioninformation [15]uintptr } diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go index d4b1e1fad3..332136b586 100644 --- a/src/runtime/export_windows_test.go +++ b/src/runtime/export_windows_test.go @@ -11,7 +11,6 @@ import "unsafe" const MaxArgs = maxArgs var ( - TestingWER = &testingWER OsYield = osyield TimeBeginPeriodRetValue = &timeBeginPeriodRetValue ) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index 03d593906e..189b4d4bb9 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -217,6 +217,7 @@ and shows goroutines created internally by the run-time. GOTRACEBACK=crash is like “system” but crashes in an operating system-specific manner instead of exiting. For example, on Unix systems, the crash raises SIGABRT to trigger a core dump. +GOTRACEBACK=wer is like “crash” but doesn't disable Windows Error Reporting (WER). For historical reasons, the GOTRACEBACK settings 0, 1, and 2 are synonyms for none, all, and system, respectively. The runtime/debug package's SetTraceback function allows increasing the diff --git a/src/runtime/relax_stub.go b/src/runtime/nonwindows_stub.go similarity index 82% rename from src/runtime/relax_stub.go rename to src/runtime/nonwindows_stub.go index e507702fc1..033f026c42 100644 --- a/src/runtime/relax_stub.go +++ b/src/runtime/nonwindows_stub.go @@ -15,3 +15,7 @@ const osRelaxMinNS = 0 // osRelax is called by the scheduler when transitioning to and from // all Ps being idle. func osRelax(relax bool) {} + +// enableWER is called by setTraceback("wer"). +// Windows Error Reporting (WER) is only supported on Windows. +func enableWER() {} diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 41f8f77848..10b445837e 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -30,6 +30,7 @@ const ( //go:cgo_import_dynamic runtime._GetConsoleMode GetConsoleMode%2 "kernel32.dll" //go:cgo_import_dynamic runtime._GetCurrentThreadId GetCurrentThreadId%0 "kernel32.dll" //go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll" +//go:cgo_import_dynamic runtime._GetErrorMode GetErrorMode%0 "kernel32.dll" //go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll" //go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll" //go:cgo_import_dynamic runtime._GetQueuedCompletionStatusEx GetQueuedCompletionStatusEx%6 "kernel32.dll" @@ -41,6 +42,7 @@ const ( //go:cgo_import_dynamic runtime._LoadLibraryExW LoadLibraryExW%3 "kernel32.dll" //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" +//go:cgo_import_dynamic runtime._RaiseFailFastException RaiseFailFastException%3 "kernel32.dll" //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll" //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll" //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll" @@ -57,6 +59,8 @@ const ( //go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll" //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll" //go:cgo_import_dynamic runtime._WaitForMultipleObjects WaitForMultipleObjects%4 "kernel32.dll" +//go:cgo_import_dynamic runtime._WerGetFlags WerGetFlags%2 "kernel32.dll" +//go:cgo_import_dynamic runtime._WerSetFlags WerSetFlags%1 "kernel32.dll" //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll" //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll" @@ -80,6 +84,7 @@ var ( _GetConsoleMode, _GetCurrentThreadId, _GetEnvironmentStringsW, + _GetErrorMode, _GetProcAddress, _GetProcessAffinityMask, _GetQueuedCompletionStatusEx, @@ -94,6 +99,7 @@ var ( _PostQueuedCompletionStatus, _QueryPerformanceCounter, _QueryPerformanceFrequency, + _RaiseFailFastException, _ResumeThread, _SetConsoleCtrlHandler, _SetErrorMode, @@ -110,6 +116,8 @@ var ( _VirtualQuery, _WaitForSingleObject, _WaitForMultipleObjects, + _WerGetFlags, + _WerSetFlags, _WriteConsoleW, _WriteFile, _ stdFunction @@ -519,7 +527,7 @@ func osinit() { loadOptionalSyscalls() - disableWER() + preventErrorDialogs() initExceptionHandler() diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index 68a090a3c7..98c5c84c01 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -513,6 +513,13 @@ func setTraceback(level string) { t = 2<