https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=5fe1f223efc6919e550ce1650d57957b6851ff41
commit 5fe1f223efc6919e550ce1650d57957b6851ff41 Author: Takashi Yano <takashi.y...@nifty.ne.jp> Date: Mon Jun 23 20:25:25 2025 +0900 Cygwin: signal: Do not suspend myself and use VEH After the commit f305ca916ad2, some stress-ng tests fail in arm64 windows. There seems to be two causes for this issue. One is that calling SuspendThread(GetCurrentThread()) may suspend myself in the kernel. Branching to sigdelayed in the kernel code does not work as expected as the original _cygtls::interrup_now() intended. The other cause is, single step exception sometimes does not trigger exception::handle() for some reason. Therefore, register vectored exception handler (VEH) and use it for single step exception instead. Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258332.html Fixes: f305ca916ad2 ("Cygwin: signal: Prevent unexpected crash on frequent SIGSEGV") Reported-by: Jeremy Drake <cyg...@jdrake.com> Reviewed-by: Corinna Vinschen <cori...@vinschen.de> Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp> (cherry picked from commit b0a9b628aad8dd35892b9da3511c434d9a61d37f) Diff: --- winsup/cygwin/exceptions.cc | 55 +++++++++++++++++++++++------------ winsup/cygwin/local_includes/cygtls.h | 1 + winsup/cygwin/local_includes/ntdll.h | 2 ++ winsup/cygwin/release/3.6.4 | 3 ++ 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index a4699b172..f79978f73 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -653,13 +653,6 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, static int NO_COPY debugging = 0; _cygtls& me = _my_tls; - if (me.suspend_on_exception) - { - SuspendThread (GetCurrentThread ()); - if (e->ExceptionCode == (DWORD) STATUS_SINGLE_STEP) - return ExceptionContinueExecution; - } - if (debugging && ++debugging < 500000) { SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL); @@ -923,6 +916,24 @@ sig_handle_tty_stop (int sig, siginfo_t *, void *) } } /* end extern "C" */ +#ifdef __x86_64__ +static LONG CALLBACK +singlestep_handler (EXCEPTION_POINTERS *ep) +{ + if (_my_tls.suspend_on_exception) + { + _my_tls.in_singlestep_handler = true; + RtlWakeAddressSingle ((void *) &_my_tls.in_singlestep_handler); + while (_my_tls.suspend_on_exception) + ; /* Don't call yield() to prevent the thread + from being suspended in the kernel. */ + if (ep->ExceptionRecord->ExceptionCode == (DWORD) STATUS_SINGLE_STEP) + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + bool _cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler, struct sigaction& siga) @@ -942,28 +953,36 @@ _cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler, a crash. To prevent this, advance execution by a single instruction by setting the trap flag (TF) before calling ResumeThread(). This will trigger either STATUS_SINGLE_STEP or the exception caused by - the instruction that Rip originally pointed to. By suspending the - targeted thread within exception::handle(), Rip no longer points + the instruction that Rip originally pointed to. By suspending the + targeted thread within singlestep_handler(), Rip no longer points to the problematic instruction, allowing safe handling of the - interrupt. As a result, Rip can be adjusted appropriately, and the - thread can resume execution without unexpected crashes. */ + interrupt. As a result, Rip can be adjusted appropriately, + and the thread can resume execution without unexpected crashes. */ if (!inside_kernel (cx, true)) { + HANDLE h_veh = AddVectoredExceptionHandler (0, singlestep_handler); cx->EFlags |= 0x100; /* Set TF (setup single step execution) */ SetThreadContext (*this, cx); suspend_on_exception = true; + in_singlestep_handler = false; + bool bool_false = false; + NTSTATUS status = STATUS_SUCCESS; ResumeThread (*this); - ULONG cnt = 0; - NTSTATUS status; - do + while (!in_singlestep_handler && NT_SUCCESS (status)) { - yield (); - status = NtQueryInformationThread (*this, ThreadSuspendCount, - &cnt, sizeof (cnt), NULL); + LARGE_INTEGER timeout; + timeout.QuadPart = -100000ULL; /* 10ms */ + status = RtlWaitOnAddress (&in_singlestep_handler, &bool_false, + sizeof (bool), &timeout); + if (status == STATUS_TIMEOUT) + break; } - while (NT_SUCCESS (status) && cnt == 0); + SuspendThread (*this); GetThreadContext (*this, cx); + RemoveVectoredExceptionHandler (h_veh); suspend_on_exception = false; + if (!NT_SUCCESS (status) || status == STATUS_TIMEOUT) + return false; /* Not interrupted */ } #endif DWORD64 &ip = cx->_CX_instPtr; diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h index 615361d3f..306497a33 100644 --- a/winsup/cygwin/local_includes/cygtls.h +++ b/winsup/cygwin/local_includes/cygtls.h @@ -204,6 +204,7 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */ __tlsstack_t stack[TLS_STACK_SIZE]; unsigned initialized; volatile bool suspend_on_exception; + volatile bool in_singlestep_handler; public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */ void init_thread (void *, DWORD (*) (void *, void *)); diff --git a/winsup/cygwin/local_includes/ntdll.h b/winsup/cygwin/local_includes/ntdll.h index 242a6a64b..29e33b197 100644 --- a/winsup/cygwin/local_includes/ntdll.h +++ b/winsup/cygwin/local_includes/ntdll.h @@ -1659,6 +1659,8 @@ extern "C" BOOLEAN); WCHAR RtlUpcaseUnicodeChar (WCHAR); NTSTATUS RtlUpcaseUnicodeString (PUNICODE_STRING, PUNICODE_STRING, BOOLEAN); + VOID RtlWakeAddressSingle (PVOID); + NTSTATUS RtlWaitOnAddress (volatile void *, PVOID, SIZE_T, PLARGE_INTEGER); NTSTATUS RtlWriteRegistryValue (ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG); #ifdef __cplusplus diff --git a/winsup/cygwin/release/3.6.4 b/winsup/cygwin/release/3.6.4 index c80a29ea4..31e6c6392 100644 --- a/winsup/cygwin/release/3.6.4 +++ b/winsup/cygwin/release/3.6.4 @@ -9,3 +9,6 @@ Fixes: - Fix creating native symlinks to `..` (it used to target `../../<dir>` instead). + +- Fix CI (stress-ng) for arm64 windows failure. + Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258332.html