# HG changeset patch # User Taylor R Campbell # Date 1744488372 0 # Sat Apr 12 20:06:12 2025 +0000 # Branch trunk # Node ID a3646a7059dabf9053d8df7d067f26ef92096f91 # Parent a5126f8e5787cbef0f8988bfb282bf54e1a671ad # EXP-Topic riastradh-pr57946-longjmpstacksigmask sparc, sparc64 longjmp: Use _UC_SIGMASK to restore signal mask. This way, restoring the signal mask and restoring the stack pointer happen atomically with respect to signal handler calls, whereas using sigprocmask would restore the signal mask _before_ the stack pointer, breaking sigaltstack. The motivation for using sigprocmask first and then setcontext later, rather than _UC_SIGMASK in setcontext, was to get SA-based libpthead sigprocmask interposition. But that's long gone and unlikely to come back. PR lib/57946: longjmp fails to restore stack first before restoring signal mask on most architectures diff -r a5126f8e5787 -r a3646a7059da lib/libc/arch/sparc/gen/longjmp.c --- a/lib/libc/arch/sparc/gen/longjmp.c Sat Apr 12 19:59:11 2025 +0000 +++ b/lib/libc/arch/sparc/gen/longjmp.c Sat Apr 12 20:06:12 2025 +0000 @@ -74,14 +74,24 @@ void memset(&uc, 0, sizeof(uc)); /* - * Set _UC_{SET,CLR}STACK according to SS_ONSTACK. + * Set _UC_CPU (restore CPU registers) and _UC_SIGMASK (restore + * the signal mask) unconditionally. * - * Restore the signal mask with sigprocmask() instead of _UC_SIGMASK, - * since libpthread may want to interpose on signal handling. + * In the distant past of SA-based libpthread with sigprocmask + * interception, we called sigprocmask here instead of using + * _UC_SIGMASK -- but that restored the signal mask before the + * stack pointer (PR lib/57946: longjmp fails to restore stack + * first before restoring signal mask on most architectures), + * which breaks sigaltstack, and SA-based libpthread is long + * gone. So we use _UC_SIGMASK. + * + * Set _UC_{SET,CLR}STACK according to SS_ONSTACK. */ - uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK); + uc.uc_flags = _UC_CPU | _UC_SIGMASK; + uc.uc_flags |= (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK); - sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL); + /* Copy signal mask */ + uc.uc_sigmask = sc->sc_mask; /* Extract PSR, PC, NPC and SP from jmp_buf */ uc.uc_mcontext.__gregs[_REG_PSR] = sc->sc_psr; diff -r a5126f8e5787 -r a3646a7059da lib/libc/arch/sparc64/gen/longjmp.c --- a/lib/libc/arch/sparc64/gen/longjmp.c Sat Apr 12 19:59:11 2025 +0000 +++ b/lib/libc/arch/sparc64/gen/longjmp.c Sat Apr 12 20:06:12 2025 +0000 @@ -72,18 +72,27 @@ void if (sc->sc_sp == 0) goto err; - /* - * Set _UC_CPU. No FPU data saved, so we can't restore - * that. Set _UC_{SET,CLR}STACK according to SS_ONSTACK - */ memset(&uc, 0, sizeof(uc)); - uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK); /* - * Set the signal mask - this is a weak symbol, so don't use - * _UC_SIGMASK in the mcontext, libpthread might override sigprocmask. + * Set _UC_CPU (restore CPU registers) and _UC_SIGMASK (restore + * the signal mask) unconditionally. + * + * In the distant past of SA-based libpthread with sigprocmask + * interception, we called sigprocmask here instead of using + * _UC_SIGMASK -- but that restored the signal mask before the + * stack pointer (PR lib/57946: longjmp fails to restore stack + * first before restoring signal mask on most architectures), + * which breaks sigaltstack, and SA-based libpthread is long + * gone. So we use _UC_SIGMASK. + * + * Set _UC_{SET,CLR}STACK according to SS_ONSTACK. */ - sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL); + uc.uc_flags = _UC_CPU | _UC_SIGMASK; + uc.uc_flags |= (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK); + + /* Copy signal mask */ + uc.uc_sigmask = sc->sc_mask; /* Fill other registers */ uc.uc_mcontext.__gregs[_REG_CCR] = sc->sc_tstate; @@ -98,6 +107,7 @@ void uc.uc_mcontext.__gregs[_REG_G7] = r->g7; uc.uc_mcontext.__gregs[_REG_O6] = sc->sc_sp; + /* No FPU data saved, so we can't restore that. */ /* Make return value non-zero */ if (val == 0) diff -r a5126f8e5787 -r a3646a7059da tests/lib/libc/setjmp/t_sigstack.c --- a/tests/lib/libc/setjmp/t_sigstack.c Sat Apr 12 19:59:11 2025 +0000 +++ b/tests/lib/libc/setjmp/t_sigstack.c Sat Apr 12 20:06:12 2025 +0000 @@ -91,13 +91,13 @@ on_sigusr1(int signo, siginfo_t *si, voi * or1k * powerpc * powerpc64 + * sparc + * sparc64 * riscv * vax * x86_64 */ -#if \ - defined __ia64__ || \ - defined __sparc__ || defined __sparc64__ +#if defined __ia64__ if (nentries > 0) atf_tc_expect_fail("PR lib/57946"); #endif