diff options
Diffstat (limited to 'go-patches')
-rw-r--r-- | go-patches/highres-timer.patch | 395 | ||||
-rw-r--r-- | go-patches/no-ctrlc-handler.patch | 184 |
2 files changed, 0 insertions, 579 deletions
diff --git a/go-patches/highres-timer.patch b/go-patches/highres-timer.patch deleted file mode 100644 index 87dd6b17..00000000 --- a/go-patches/highres-timer.patch +++ /dev/null @@ -1,395 +0,0 @@ -From 2975b381dc3f559a2eef875582d73cec00ab6b17 Mon Sep 17 00:00:00 2001 -From: Alex Brainman <alex.brainman@gmail.com> -Date: Sun, 19 Jul 2020 16:06:48 +1000 -Subject: [PATCH] runtime: use CreateWaitableTimerEx to implement usleep - -@jstarks suggested that recent versions of Windows provide access to high resolution timers. See - -https://github.com/golang/go/issues/8687#issuecomment-656259353 - -for details. - -I tried to run this C program on my Windows 10 computer - -``` - #include <stdio.h> - #include <Windows.h> - - #pragma comment(lib, "Winmm.lib") - -// Apparently this is already defined when I use msvc cl. -//#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION = 0x00000002; - -int usleep(HANDLE timer, LONGLONG d) { - LARGE_INTEGER liDueTime; - DWORD ret; - LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds; - LARGE_INTEGER Frequency; - - QueryPerformanceFrequency(&Frequency); - QueryPerformanceCounter(&StartingTime); - - liDueTime.QuadPart = d; - liDueTime.QuadPart = liDueTime.QuadPart * 10; // us into 100 of ns units - liDueTime.QuadPart = -liDueTime.QuadPart; // negative for relative dure time - - if (!SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, 0)) { - printf("SetWaitableTimer failed: errno=%d\n", GetLastError()); - return 1; - } - - ret = WaitForSingleObject(timer, INFINITE); - if (ret != WAIT_OBJECT_0) { - printf("WaitForSingleObject failed: ret=%d errno=%d\n", ret, GetLastError()); - return 1; - } - - QueryPerformanceCounter(&EndingTime); - ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; - ElapsedMicroseconds.QuadPart *= 1000000; - ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; - - printf("delay is %lld us - slept for %lld us\n", d, ElapsedMicroseconds.QuadPart); - - return 0; -} - -int testTimer(DWORD createFlag) -{ - HANDLE timer; - - timer = CreateWaitableTimerEx(NULL, NULL, createFlag, TIMER_ALL_ACCESS); - if (timer == NULL) { - printf("CreateWaitableTimerEx failed: errno=%d\n", GetLastError()); - return 1; - } - - usleep(timer, 1000LL); - usleep(timer, 100LL); - usleep(timer, 10LL); - usleep(timer, 1LL); - - CloseHandle(timer); - - return 0; -} - -int main() -{ - printf("\n1. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is off\n"); - testTimer(0); - - printf("\n2. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is off\n"); - testTimer(CREATE_WAITABLE_TIMER_HIGH_RESOLUTION); - - timeBeginPeriod(1); - - printf("\n3. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is on\n"); - testTimer(0); - - printf("\n4. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is on\n"); - testTimer(CREATE_WAITABLE_TIMER_HIGH_RESOLUTION); -} -``` - -and I see this output - -``` -1. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is off -delay is 1000 us - slept for 4045 us -delay is 100 us - slept for 3915 us -delay is 10 us - slept for 3291 us -delay is 1 us - slept for 2234 us - -2. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is off -delay is 1000 us - slept for 1076 us -delay is 100 us - slept for 569 us -delay is 10 us - slept for 585 us -delay is 1 us - slept for 17 us - -3. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is on -delay is 1000 us - slept for 742 us -delay is 100 us - slept for 893 us -delay is 10 us - slept for 414 us -delay is 1 us - slept for 920 us - -4. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is on -delay is 1000 us - slept for 1466 us -delay is 100 us - slept for 559 us -delay is 10 us - slept for 535 us -delay is 1 us - slept for 5 us -``` - -That shows, that indeed using CREATE_WAITABLE_TIMER_HIGH_RESOLUTION -will provide sleeps as low as about 500 microseconds, while our -current approach provides about 1 millisecond sleep. - -New approach also does not require for timeBeginPeriod to be on, -so this change solves long standing problem with go programs draining -laptop battery, because it calls timeBeginPeriod. - -This change will only run on systems where -CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag is available. If not -available, the runtime will fallback to original code that uses -timeBeginPeriod. - -This is how this change affects benchmark reported in issue #14790 - -name old time/op new time/op delta -ChanToSyscallPing 1.05ms ± 2% 0.68ms ±11% -35.43% (p=0.000 n=10+10) - -The benchmark was run with GOMAXPROCS set to 1. - -Fixes #8687 -Updates #14790 - -Change-Id: I5b97ba58289c088c17c05292e12e45285c467eae ---- - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index a62e941..46f4a23 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -21,6 +21,7 @@ - //go:cgo_import_dynamic runtime._CreateIoCompletionPort CreateIoCompletionPort%4 "kernel32.dll" - //go:cgo_import_dynamic runtime._CreateThread CreateThread%6 "kernel32.dll" - //go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA%3 "kernel32.dll" -+//go:cgo_import_dynamic runtime._CreateWaitableTimerExW CreateWaitableTimerExW%4 "kernel32.dll" - //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll" - //go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll" - //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll" -@@ -68,6 +69,7 @@ - _CreateIoCompletionPort, - _CreateThread, - _CreateWaitableTimerA, -+ _CreateWaitableTimerExW, - _DuplicateHandle, - _ExitProcess, - _FreeEnvironmentStringsW, -@@ -151,6 +153,8 @@ - waitsema uintptr // semaphore for parking on locks - resumesema uintptr // semaphore to indicate suspend/resume - -+ highResTimer uintptr // high resolution timer handle used in usleep -+ - // preemptExtLock synchronizes preemptM with entry/exit from - // external C code. - // -@@ -407,6 +411,12 @@ - // if we're already using the CPU, but if all Ps are idle there's no - // need to consume extra power to drive the high-res timer. - func osRelax(relax bool) uint32 { -+ if haveHighResTimer { -+ // Only call timeBeginPeriod/timeEndPeriod, if -+ // high resolution timer is not available. -+ return 0 -+ } -+ - if relax { - return uint32(stdcall1(_timeEndPeriod, 1)) - } else { -@@ -414,6 +424,37 @@ - } - } - -+// haveHighResTimer determines, if CreateWaitableTimerEx -+// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag is available. -+var haveHighResTimer = false -+ -+// createHighResTimer calls CreateWaitableTimerEx with -+// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag to create high -+// resolution timer. createHighResTimer returns new timer -+// handle or 0, if CreateWaitableTimerEx failed. -+func createHighResTimer() uintptr { -+ const ( -+ // As per @jstarks, see -+ // https://github.com/golang/go/issues/8687#issuecomment-656259353 -+ _CREATE_WAITABLE_TIMER_HIGH_RESOLUTION = 0x00000002 -+ _TIMER_ALL_ACCESS = 0x1F0003 -+ ) -+ return stdcall4(_CreateWaitableTimerExW, 0, 0, _CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, _TIMER_ALL_ACCESS) -+} -+ -+func initHighResTimer() { -+ if GOARCH == "arm" { -+ // TODO: Not yet implemented. -+ return -+ } -+ h := createHighResTimer() -+ if h != 0 { -+ haveHighResTimer = true -+ usleep2Addr = unsafe.Pointer(funcPC(usleep2HighRes)) -+ stdcall1(_CloseHandle, h) -+ } -+} -+ - func osinit() { - asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) - usleep2Addr = unsafe.Pointer(funcPC(usleep2)) -@@ -429,6 +470,7 @@ - - stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) - -+ initHighResTimer() - timeBeginPeriodRetValue = osRelax(false) - - ncpu = getproccount() -@@ -844,9 +886,20 @@ - var thandle uintptr - stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) - -+ // Configure usleep timer, if possible. -+ var timer uintptr -+ if haveHighResTimer { -+ timer = createHighResTimer() -+ if timer == 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 -@@ -884,6 +937,10 @@ - lock(&mp.threadLock) - stdcall1(_CloseHandle, mp.thread) - mp.thread = 0 -+ if mp.highResTimer != 0 { -+ stdcall1(_CloseHandle, mp.highResTimer) -+ mp.highResTimer = 0 -+ } - unlock(&mp.threadLock) - } - -@@ -979,6 +1036,7 @@ - // in sys_windows_386.s and sys_windows_amd64.s - func onosstack(fn unsafe.Pointer, arg uint32) - func usleep2(usec uint32) -+func usleep2HighRes(usec uint32) - func switchtothread() - - var usleep2Addr unsafe.Pointer -diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s -index 9e1f409..4ac1527 100644 ---- a/src/runtime/sys_windows_386.s -+++ b/src/runtime/sys_windows_386.s -@@ -428,6 +428,42 @@ - MOVL BP, SP - RET - -+// Runs on OS stack. duration (in 100ns units) is in BX. -+TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36 -+ // Want negative 100ns units. -+ NEGL BX -+ MOVL $-1, hi-4(SP) -+ MOVL BX, lo-8(SP) -+ -+ get_tls(CX) -+ MOVL g(CX), CX -+ MOVL g_m(CX), CX -+ MOVL (m_mOS+mOS_highResTimer)(CX), CX -+ MOVL CX, saved_timer-12(SP) -+ -+ MOVL $0, fResume-16(SP) -+ MOVL $0, lpArgToCompletionRoutine-20(SP) -+ MOVL $0, pfnCompletionRoutine-24(SP) -+ MOVL $0, lPeriod-28(SP) -+ LEAL lo-8(SP), BX -+ MOVL BX, lpDueTime-32(SP) -+ MOVL CX, hTimer-36(SP) -+ MOVL SP, BP -+ MOVL runtime·_SetWaitableTimer(SB), AX -+ CALL AX -+ MOVL BP, SP -+ -+ MOVL $0, ptime-28(SP) -+ MOVL $0, alertable-32(SP) -+ MOVL saved_timer-12(SP), CX -+ MOVL CX, handle-36(SP) -+ MOVL SP, BP -+ MOVL runtime·_NtWaitForSingleObject(SB), AX -+ CALL AX -+ MOVL BP, SP -+ -+ RET -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT,$0 - MOVL SP, BP -diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s -index 6c8eecd..8475425 100644 ---- a/src/runtime/sys_windows_amd64.s -+++ b/src/runtime/sys_windows_amd64.s -@@ -457,6 +457,38 @@ - MOVQ 40(SP), SP - RET - -+// Runs on OS stack. duration (in 100ns units) is in BX. -+TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72 -+ MOVQ SP, AX -+ ANDQ $~15, SP // alignment as per Windows requirement -+ MOVQ AX, 64(SP) -+ -+ get_tls(CX) -+ MOVQ g(CX), CX -+ MOVQ g_m(CX), CX -+ MOVQ (m_mOS+mOS_highResTimer)(CX), CX // hTimer -+ MOVQ CX, 48(SP) // save hTimer for later -+ // Want negative 100ns units. -+ NEGQ BX -+ LEAQ 56(SP), DX // lpDueTime -+ MOVQ BX, (DX) -+ MOVQ $0, R8 // lPeriod -+ MOVQ $0, R9 // pfnCompletionRoutine -+ MOVQ $0, AX -+ MOVQ AX, 32(SP) // lpArgToCompletionRoutine -+ MOVQ AX, 40(SP) // fResume -+ MOVQ runtime·_SetWaitableTimer(SB), AX -+ CALL AX -+ -+ MOVQ 48(SP), CX // handle -+ MOVQ $0, DX // alertable -+ MOVQ $0, R8 // ptime -+ MOVQ runtime·_NtWaitForSingleObject(SB), AX -+ CALL AX -+ -+ MOVQ 64(SP), SP -+ RET -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0 - MOVQ SP, AX -diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s -index 256b5ff..e6c61a4 100644 ---- a/src/runtime/sys_windows_arm.s -+++ b/src/runtime/sys_windows_arm.s -@@ -468,6 +468,24 @@ - MOVW R4, R13 // Restore SP - MOVM.IA.W (R13), [R4, R15] // pop {R4, pc} - -+// Runs on OS stack. Duration (in 100ns units) is in R0. -+// TODO: neeeds to be implemented properly. -+TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$0 -+ MOVM.DB.W [R4, R14], (R13) // push {r4, lr} -+ MOVW R13, R4 // Save SP -+ SUB $8, R13 // R13 = R13 - 8 -+ BIC $0x7, R13 // Align SP for ABI -+ RSB $0, R0, R3 // R3 = -R0 -+ MOVW $0, R1 // R1 = FALSE (alertable) -+ MOVW $-1, R0 // R0 = handle -+ MOVW R13, R2 // R2 = pTime -+ MOVW R3, 0(R2) // time_lo -+ MOVW R0, 4(R2) // time_hi -+ MOVW runtime·_NtWaitForSingleObject(SB), R3 -+ BL (R3) -+ MOVW R4, R13 // Restore SP -+ MOVM.IA.W (R13), [R4, R15] // pop {R4, pc} -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0 - MOVM.DB.W [R4, R14], (R13) // push {R4, lr} diff --git a/go-patches/no-ctrlc-handler.patch b/go-patches/no-ctrlc-handler.patch deleted file mode 100644 index 157ed88f..00000000 --- a/go-patches/no-ctrlc-handler.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 8bc7bff3bff8f61312f8d2307cfe2e433d356c31 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" <Jason@zx2c4.com> -Date: Fri, 11 Sep 2020 13:04:11 +0200 -Subject: [PATCH 1/2] Revert "[release-branch.go1.15] runtime: detect services - in signal handler" - -This reverts commit b1253d24e159129c778377c3a2a0bde15904a417. ---- - src/runtime/os_windows.go | 73 +++------------------------------------ - 1 file changed, 4 insertions(+), 69 deletions(-) - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index 769197db46..a584ada702 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -36,10 +36,7 @@ const ( - //go:cgo_import_dynamic runtime._SetThreadContext SetThreadContext%2 "kernel32.dll" - //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" - //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" --//go:cgo_import_dynamic runtime._OpenProcess OpenProcess%3 "kernel32.dll" - //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" --//go:cgo_import_dynamic runtime._ProcessIdToSessionId ProcessIdToSessionId%2 "kernel32.dll" --//go:cgo_import_dynamic runtime._QueryFullProcessImageNameA QueryFullProcessImageNameA%4 "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" -@@ -87,10 +84,7 @@ var ( - _SetThreadContext, - _LoadLibraryW, - _LoadLibraryA, -- _OpenProcess, - _PostQueuedCompletionStatus, -- _ProcessIdToSessionId, -- _QueryFullProcessImageNameA, - _QueryPerformanceCounter, - _QueryPerformanceFrequency, - _ResumeThread, -@@ -134,8 +128,7 @@ var ( - // Load ntdll.dll manually during startup, otherwise Mingw - // links wrong printf function to cgo executable (see issue - // 12030 for details). -- _NtWaitForSingleObject stdFunction -- _NtQueryInformationProcess stdFunction -+ _NtWaitForSingleObject stdFunction - - // These are from non-kernel32.dll, so we prefer to LoadLibraryEx them. - _timeBeginPeriod, -@@ -262,7 +255,6 @@ func loadOptionalSyscalls() { - throw("ntdll.dll not found") - } - _NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000")) -- _NtQueryInformationProcess = windowsFindfunc(n32, []byte("NtQueryInformationProcess\000")) - - if GOARCH == "arm" { - _QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000")) -@@ -1003,63 +995,6 @@ func usleep(us uint32) { - onosstack(usleep2Addr, 10*us) - } - --// isWindowsService returns whether the process is currently executing as a --// Windows service. The below technique looks a bit hairy, but it's actually --// exactly what the .NET framework does for the similarly named function: --// https://github.com/dotnet/extensions/blob/f4066026ca06984b07e90e61a6390ac38152ba93/src/Hosting/WindowsServices/src/WindowsServiceHelpers.cs#L26-L31 --// Specifically, it looks up whether the parent process has session ID zero --// and is called "services". --func isWindowsService() bool { -- const ( -- _CURRENT_PROCESS = ^uintptr(0) -- _PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 -- ) -- // pbi is a PROCESS_BASIC_INFORMATION struct, where we just care about -- // the 6th pointer inside of it, which contains the pid of the process -- // parent: -- // https://github.com/wine-mirror/wine/blob/42cb7d2ad1caba08de235e6319b9967296b5d554/include/winternl.h#L1294 -- var pbi [6]uintptr -- var pbiLen uint32 -- err := stdcall5(_NtQueryInformationProcess, _CURRENT_PROCESS, 0, uintptr(unsafe.Pointer(&pbi[0])), uintptr(unsafe.Sizeof(pbi)), uintptr(unsafe.Pointer(&pbiLen))) -- if err != 0 { -- return false -- } -- var psid uint32 -- err = stdcall2(_ProcessIdToSessionId, pbi[5], uintptr(unsafe.Pointer(&psid))) -- if err == 0 || psid != 0 { -- return false -- } -- pproc := stdcall3(_OpenProcess, _PROCESS_QUERY_LIMITED_INFORMATION, 0, pbi[5]) -- if pproc == 0 { -- return false -- } -- defer stdcall1(_CloseHandle, pproc) -- // exeName gets the path to the executable image of the parent process -- var exeName [261]byte -- exeNameLen := uint32(len(exeName) - 1) -- err = stdcall4(_QueryFullProcessImageNameA, pproc, 0, uintptr(unsafe.Pointer(&exeName[0])), uintptr(unsafe.Pointer(&exeNameLen))) -- if err == 0 || exeNameLen == 0 { -- return false -- } -- servicesLower := "services.exe" -- servicesUpper := "SERVICES.EXE" -- i := int(exeNameLen) - 1 -- j := len(servicesLower) - 1 -- if i < j { -- return false -- } -- for { -- if j == -1 { -- return i == -1 || exeName[i] == '\\' -- } -- if exeName[i] != servicesLower[j] && exeName[i] != servicesUpper[j] { -- return false -- } -- i-- -- j-- -- } --} -- - func ctrlhandler1(_type uint32) uint32 { - var s uint32 - -@@ -1075,9 +1010,9 @@ func ctrlhandler1(_type uint32) uint32 { - if sigsend(s) { - return 1 - } -- if !islibrary && !isarchive && !isWindowsService() { -- // Only exit the program if we don't have a DLL or service. -- // See https://golang.org/issues/35965 and https://golang.org/issues/40167 -+ if !islibrary && !isarchive { -+ // Only exit the program if we don't have a DLL. -+ // See https://golang.org/issues/35965. - exit(2) // SIGINT, SIGTERM, etc - } - return 0 --- -2.28.0 - -From 84cc2046962e754af08f99327561be2e979eaf16 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" <Jason@zx2c4.com> -Date: Tue, 14 Jul 2020 01:41:03 -0600 -Subject: [PATCH 2/2] runtime: do not explicitly exit on ctrl handler - -The default ctrl+c handler should process exits in situations where it -makes sense, like console apps, but not in situations where it doesn't, -like libraries or services. Therefore, we should remove the exit(2) so -that the default handler is used for this. This also uses the more -proper windows exit code of STATUS_CONTROL_C_EXIT, with the base case -handler installed by KernelBase.dll. In particular, this helps in the -case of services, which previously would terminate when receiving -shutdown signals, instead of passing them onward to the service program. -In this CL, contrary to CL 244959, we do not need to special case -services with expensive detection algorithms, or rely on hard-coded -library/archive flags. - -Fixes #40167. -Fixes #40074. - -Change-Id: I9bf6ed6f65cefeff754d270aa33fa4df8d0b451f -Reviewed-on: https://go-review.googlesource.com/c/go/+/243597 -Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> -TryBot-Result: Gobot Gobot <gobot@golang.org> -Reviewed-by: Alex Brainman <alex.brainman@gmail.com> -Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com> ---- - src/runtime/os_windows.go | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index a584ada702..a62e941229 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -1010,11 +1010,6 @@ func ctrlhandler1(_type uint32) uint32 { - if sigsend(s) { - return 1 - } -- if !islibrary && !isarchive { -- // Only exit the program if we don't have a DLL. -- // See https://golang.org/issues/35965. -- exit(2) // SIGINT, SIGTERM, etc -- } - return 0 - } - --- -2.28.0 - |