git: 0143078248bb - stable/15 - linux(4): Fix signal mask restoration in epoll_pwait(2)/epoll_pwait2(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 04 Oct 2026 00:34:22 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=0143078248bb4caf39f23c9075b2afbede52e70d
commit 0143078248bb4caf39f23c9075b2afbede52e70d
Author: Grzegorz Junka <list1@gjunka.com>
AuthorDate: 2026-09-27 19:22:20 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-10-04 00:33:40 +0000
linux(4): Fix signal mask restoration in epoll_pwait(2)/epoll_pwait2(2)
PR: 298878
(cherry picked from commit 16a284b1cdfd45ba99c2723e7f88497e76b235ad)
---
sys/compat/linux/linux_event.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c
index fc3ef7c3e90a..de313aefff97 100644
--- a/sys/compat/linux/linux_event.c
+++ b/sys/compat/linux/linux_event.c
@@ -376,7 +376,6 @@ linux_epoll_wait_ts(struct thread *td, int epfd, struct epoll_event *events,
NULL};
cap_rights_t rights;
struct file *epfp;
- sigset_t omask;
int error;
if (maxevents <= 0 || maxevents > LINUX_MAX_EVENTS)
@@ -392,16 +391,10 @@ linux_epoll_wait_ts(struct thread *td, int epfd, struct epoll_event *events,
}
if (uset != NULL) {
error = kern_sigprocmask(td, SIG_SETMASK, uset,
- &omask, 0);
+ &td->td_oldsigmask, 0);
if (error != 0)
goto leave;
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);
}
coargs.leventlist = events;
@@ -420,9 +413,19 @@ linux_epoll_wait_ts(struct thread *td, int epfd, struct epoll_event *events,
if (error == 0)
td->td_retval[0] = coargs.count;
- if (uset != NULL)
- error = kern_sigprocmask(td, SIG_SETMASK, &omask,
- NULL, 0);
+ if (uset != NULL) {
+ /*
+ * Make sure that ast() is called on return to usermode and
+ * TDP_OLDMASK is cleared, restoring the old sigmask from
+ * td_oldsigmask. As on Linux, if we were interrupted, deliver
+ * the signal with the temporary mask in place; otherwise
+ * restore the old mask before any signal can be delivered.
+ */
+ if (error == EINTR)
+ ast_sched(td, TDA_SIGSUSPEND);
+ else
+ ast_sched(td, TDA_PSELECT);
+ }
leave:
fdrop(epfp, td);
return (error);