# HG changeset patch # User Taylor R Campbell # Date 1744487951 0 # Sat Apr 12 19:59:11 2025 +0000 # Branch trunk # Node ID a5126f8e5787cbef0f8988bfb282bf54e1a671ad # Parent d857f250705966f1fb6141eae04307965f26134b # EXP-Topic riastradh-pr57946-longjmpstacksigmask mips 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 d857f2507059 -r a5126f8e5787 lib/libc/arch/mips/gen/longjmp.c --- a/lib/libc/arch/mips/gen/longjmp.c Sat Apr 12 19:57:17 2025 +0000 +++ b/lib/libc/arch/mips/gen/longjmp.c Sat Apr 12 19:59:11 2025 +0000 @@ -57,18 +57,28 @@ void val = 1; /* - * 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); - - sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL); + uc.uc_flags = _UC_CPU | _UC_SIGMASK; + uc.uc_flags |= (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK); /* Clear uc_link */ uc.uc_link = 0; + /* Copy signal mask */ + uc.uc_sigmask = sc->sc_mask; + /* Save return value in context */ uc.uc_mcontext.__gregs[_REG_V0] = val; diff -r d857f2507059 -r a5126f8e5787 tests/lib/libc/setjmp/t_sigstack.c --- a/tests/lib/libc/setjmp/t_sigstack.c Sat Apr 12 19:57:17 2025 +0000 +++ b/tests/lib/libc/setjmp/t_sigstack.c Sat Apr 12 19:59:11 2025 +0000 @@ -87,6 +87,7 @@ on_sigusr1(int signo, siginfo_t *si, voi * hppa * i386 * m68k + * mips * or1k * powerpc * powerpc64 @@ -95,7 +96,7 @@ on_sigusr1(int signo, siginfo_t *si, voi * x86_64 */ #if \ - defined __ia64__ || defined __mips__ || \ + defined __ia64__ || \ defined __sparc__ || defined __sparc64__ if (nentries > 0) atf_tc_expect_fail("PR lib/57946");