From nobody Sun Sep 27 19:26:35 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4htDvh3B7jz6tvkZ for ; Sun, 27 Sep 2026 19:26:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4htDvh2hHMz3RJy for ; Sun, 27 Sep 2026 19:26:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790537200; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=h3IYJ1+jcY6BgyGok3ZAlyIxfsg3xRWMsUbYiOId++Y=; b=KDRGnhsa5FGdRA/ZQzgdD4hE7hp1RycAYFJTMrCPDtBPlXyh/7L2iJwOJVAeTqwFsqG6Ho b2Sli1B/+wS7tAeI+ehUgSAjDaNMNVimO0JKCHnTlYWq4vEj33G4jcD/7GLHyfohdMLbtY yeMuujsdLabqFnV/EBnATQcancbc1du/1A7WQ6f99l9N6z+bB2Qs/9agwcd+CHpt9wvp33 CwNn75nt4LOLQSh8ThP00AC/ptuAd7OnTDt5teSde0KHVxUPakKaqsVoGqle/m4zsaDBLY krEICVtTpfzEaE9vFr9kE55fqcPn3EKZHHeV450q0JAnkkCTf2OiRiKNSJ/VYQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1790537200; b=qRvciyjSERCYOx0W0G1WwGO8pE8lOKsNCzapL5auGPgcqY8WYnrji6S0dhuvIv9A2yypml vrUbQ15e51VofUKDGuCKMLl7bEFVtqn36W3Ky98GurbL+3Dujj4wVZuhxzTiFSVUGaEozV M856da0xKPh58A0OrjTpu6cpF6t9qXB7jOgCO8uqVvFuKTXDyc0wIlG+uv5GTz7LS1JbfN lGIhOG8bd1bZvklZEuBsoeZo3wdRQ4y0gK3+0OTM+E5IP1DaG9XAgAZ2mkDe1iLTiTceVA E0SFZ284/n8hRrpw+fdOWwVXjhs6IFfvP0/jpTwDut1gqNyA3xmCQUNDzeKJcQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790537200; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=h3IYJ1+jcY6BgyGok3ZAlyIxfsg3xRWMsUbYiOId++Y=; b=a7L7gwipXpFBFtL1VLBZTtz8E3Uc1oNzj+6dUnz5ZPSu3px+dEk7YcNIIa1RQxfS2xubio fleC4cETLksGlQVjhDuN/7CbtknxJuzInjX6bqew+2/GSQjzsfcMZLW73V6ouc3brn6Ouf xdgsQvUDlAL+PHIOuyoQARqQaVak50IpQldIc2T4d0WQl8lMCD3SORd9IG+/HjbqKFozEJ KV4ndFq6dmFOmYpo8PGbzS4JdPNTRATu3Me+bKqxWuaCcsZWUB8SPjkRj61moPNXmR8lrH x4t9fI2B3q4xwjxTeHLAttarnFfwzo4lEfzltkb2H+AQoBvdLOotshgAqyaEjw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4htDvh1kXvzvtT for ; Sun, 27 Sep 2026 19:26:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 417a8 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 27 Sep 2026 19:26:35 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Grzegorz Junka From: Konstantin Belousov Subject: git: 16a284b1cdfd - main - linux(4): Fix signal mask restoration in epoll_pwait(2)/epoll_pwait2(2) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 16a284b1cdfd45ba99c2723e7f88497e76b235ad Auto-Submitted: auto-generated Date: Sun, 27 Sep 2026 19:26:35 +0000 Message-Id: <6ab96deb.417a8.31c39a58@gitrepo.freebsd.org> The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=16a284b1cdfd45ba99c2723e7f88497e76b235ad commit 16a284b1cdfd45ba99c2723e7f88497e76b235ad Author: Grzegorz Junka AuthorDate: 2026-09-27 19:22:20 +0000 Commit: Konstantin Belousov CommitDate: 2026-09-27 19:22:20 +0000 linux(4): Fix signal mask restoration in epoll_pwait(2)/epoll_pwait2(2) Since 80c7315d17ce ("Restore signal mask in epoll_pwait.") the caller's signal mask is saved in a local variable, but TDP_OLDMASK is still set and the TDA_SIGSUSPEND AST is still scheduled. On return to user mode that AST, or postsig() if a signal is delivered, then installs td_oldsigmask, which this code never writes and which holds whatever mask the thread had at its last sigsuspend(2), pselect(2) or ppoll(2). As a result every epoll_pwait(2)/epoll_pwait2(2) call with a non-NULL sigmask can leave the thread with a stale signal mask. In addition, the explicit restore at the end overwrote the return value, so EINTR (and any other error) was reported to user space as 0. Save the old mask in td_oldsigmask and let the AST restore it, as kern_pselect() and kern_poll_kfds() do: schedule TDA_SIGSUSPEND if the wait was interrupted, so the signal is delivered with the temporary mask in place, and TDA_PSELECT otherwise. This matches Linux, which restores the saved mask unless the syscall returns -EINTR. This deadlocks Bun-based programs such as Claude Code (>= 2.1.269) and opencode. JavaScriptCore suspends threads for conservative GC stack scanning by sending SIGPWR and waiting for the target's handler, which calls sigsuspend(2) with SIGPWR blocked. Afterwards td_oldsigmask contains SIGPWR, the event loop's next epoll_pwait2(2) (Bun always passes an empty sigmask) blocks SIGPWR on the main thread, and the next GC suspend request waits forever. PR: 298878 Fixes: 80c7315d17ce ("Restore signal mask in epoll_pwait.") MFC after: 1 week --- 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);