[newlib-cygwin/cygwin-3_5-branch] Cygwin: setjmp/longjmp: decrement incyg after signal handling

Corinna Vinschen corinna@sourceware.org
Fri Dec 6 10:47:43 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=60fa8d793f867d896b824c66789c48e86dec4ea7

commit 60fa8d793f867d896b824c66789c48e86dec4ea7
Author:     Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Wed Dec 4 13:50:17 2024 +0100
Commit:     Corinna Vinschen <corinna@vinschen.de>
CommitDate: Fri Dec 6 11:43:17 2024 +0100

    Cygwin: setjmp/longjmp: decrement incyg after signal handling
    
    Commit 0b6fbd396ca2f ("* exceptions.cc (_cygtls::interrupt_now): Revert
    to checking for "spinning" when choosing to defer signal.") introduced
    a bug in the loop inside the stabilize_sig_stack subroutine:
    
    First, stabilize_sig_stack grabs the stacklock. The _cygtls::incyg
    flag is then incremented before checking if a signal has to be handled
    for the current thread.
    
    If no signal waits, the code simply jumps out, decrements _cygtls::incyg
    and returns to the caller, which eventually releases the stacklock.
    
    However, if a signal is waiting, stabilize_sig_stack releases the
    stacklock, calls _cygtls::call_signal_handler(), and returns to
    the start of the subroutine, trying to grab the lock.
    
    After grabbing the lock, it increments _cygtls::incyg... wait...
    again?
    
    The loop does not decrement _cygtls::incyg after
    _cygtls::call_signal_handler(), which returns with _cygtls::incyg
    set to 1.  So it increments incyg to 2.  If no other signal is
    waiting, stabilize_sig_stack jumps out and decrements _cygtls::incyg
    to 1.  Eventually, setjmp or longjmp both will return to user
    code with _cygtls::incyg set to 1.  This *may* be fixed at some later
    point when signals arrive, but there will be a time when the application
    runs in user code with broken signal handling.
    
    Fixes: 0b6fbd396ca2f ("* exceptions.cc (_cygtls::interrupt_now): Revert to checking for "spinning" when choosing to defer signal.")
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
    (cherry picked from commit 41e1013e6846f1774dfec085ff983990f67e6437)

Diff:
---
 winsup/cygwin/scripts/gendef | 1 +
 1 file changed, 1 insertion(+)

diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef
index bb87ab55e557..e02d3503cc75 100755
--- a/winsup/cygwin/scripts/gendef
+++ b/winsup/cygwin/scripts/gendef
@@ -334,6 +334,7 @@ stabilize_sig_stack:
 	movq	\$_cygtls.start_offset,%rcx	# point to beginning
 	addq	%r12,%rcx			#  of tls block
 	call	_ZN7_cygtls19call_signal_handlerEv
+	decl	_cygtls.incyg(%r12)
 	jmp	1b
 3:	decl	_cygtls.incyg(%r12)
 	addq	\$0x20,%rsp


More information about the Cygwin-cvs mailing list