diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1048,15 +1048,32 @@ &td->td_oldsigmask, 0); if (error != 0) return (error); - td->td_pflags |= TDP_OLDMASK; + } + error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits); + if (error == EINTR) { /* * Make sure that ast() is called on return to * usermode and TDP_OLDMASK is cleared, restoring old * sigmask. */ + td->td_pflags |= TDP_OLDMASK; ast_sched(td, TDA_SIGSUSPEND); + } else { + int serror __diagused; + + /* *select(2) should never restart. */ + MPASS(error != ERESTART); + + /* + * Restore the signal mask before we return if we didn't get + * interrupted in sleep. The caller is likely not expecting a + * signal to hit that it can't detect by checking for EINTR. + */ + serror = kern_sigprocmask(td, SIG_SETMASK, &td->td_oldsigmask, + NULL, 0); + MPASS(serror == 0); } - error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits); + return (error); } @@ -1527,13 +1544,6 @@ &td->td_oldsigmask, 0); if (error) return (error); - td->td_pflags |= TDP_OLDMASK; - /* - * Make sure that ast() is called on return to - * usermode and TDP_OLDMASK is cleared, restoring old - * sigmask. - */ - ast_sched(td, TDA_SIGSUSPEND); } seltdinit(td); @@ -1556,6 +1566,28 @@ error = EINTR; if (error == EWOULDBLOCK) error = 0; + + if (error == EINTR) { + /* + * Make sure that ast() is called on return to + * usermode and TDP_OLDMASK is cleared, restoring old + * sigmask. + */ + td->td_pflags |= TDP_OLDMASK; + ast_sched(td, TDA_SIGSUSPEND); + } else { + int serror __diagused; + + /* + * Restore the signal mask before we return if we didn't get + * interrupted in sleep. The caller is likely not expecting a + * signal to hit that it can't detect by checking for EINTR. + */ + serror = kern_sigprocmask(td, SIG_SETMASK, &td->td_oldsigmask, + NULL, 0); + MPASS(serror == 0); + } + return (error); }