svn commit: r360940 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Mon May 11 22:38:33 UTC 2020
Author: kib
Date: Mon May 11 22:38:32 2020
New Revision: 360940
URL: https://svnweb.freebsd.org/changeset/base/360940
Log:
sigfastblock: fix delivery of the pending signals in single-threaded processes.
If single-threaded process receives a signal during critical section
established by sigfastblock(2) word, unblock did not caused signal
delivery because sigfastblock(SIGFASTBLOCK_UNBLOCK) failed to request
ast handling of the pending signals.
Set TDF_ASTPENDING | TDF_NEEDSIGCHK on unblock or when kernel forces
end of sigfastblock critical section, to cause syscall exit to recheck
and deliver any signal pending.
Reported by: corydoras at ridiculousfish.com
PR: 246385
Sponsored by: The FreeBSD Foundation
Modified:
head/sys/kern/kern_sig.c
Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c Mon May 11 22:26:39 2020 (r360939)
+++ head/sys/kern/kern_sig.c Mon May 11 22:38:32 2020 (r360940)
@@ -3976,6 +3976,22 @@ sigfastblock_fetch_sig(struct thread *td, bool sendsig
return (true);
}
+static void
+sigfastblock_resched(struct thread *td, bool resched)
+{
+ struct proc *p;
+
+ if (resched) {
+ p = td->td_proc;
+ PROC_LOCK(p);
+ reschedule_signals(p, td->td_sigmask, 0);
+ PROC_UNLOCK(p);
+ }
+ thread_lock(td);
+ td->td_flags |= TDF_ASTPENDING | TDF_NEEDSIGCHK;
+ thread_unlock(td);
+}
+
int
sys_sigfastblock(struct thread *td, struct sigfastblock_args *uap)
{
@@ -4046,11 +4062,8 @@ sys_sigfastblock(struct thread *td, struct sigfastbloc
* signals to current thread. But notify others about
* fake unblock.
*/
- if (error == 0 && p->p_numthreads != 1) {
- PROC_LOCK(p);
- reschedule_signals(p, td->td_sigmask, 0);
- PROC_UNLOCK(p);
- }
+ sigfastblock_resched(td, error == 0 && p->p_numthreads != 1);
+
break;
case SIGFASTBLOCK_UNSETPTR:
@@ -4079,7 +4092,6 @@ sys_sigfastblock(struct thread *td, struct sigfastbloc
void
sigfastblock_clear(struct thread *td)
{
- struct proc *p;
bool resched;
if ((td->td_pflags & TDP_SIGFASTBLOCK) == 0)
@@ -4088,12 +4100,7 @@ sigfastblock_clear(struct thread *td)
resched = (td->td_pflags & TDP_SIGFASTPENDING) != 0 ||
SIGPENDING(td);
td->td_pflags &= ~(TDP_SIGFASTBLOCK | TDP_SIGFASTPENDING);
- if (resched) {
- p = td->td_proc;
- PROC_LOCK(p);
- reschedule_signals(p, td->td_sigmask, 0);
- PROC_UNLOCK(p);
- }
+ sigfastblock_resched(td, resched);
}
void
More information about the svn-src-all
mailing list