Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143118990
D41128.id125096.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D41128.id125096.diff
View Options
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -862,7 +862,7 @@
static int curfail;
static struct timeval lastfail;
int flags, pages;
- bool killsx_locked;
+ bool killsx_locked, singlethreaded;
flags = fr->fr_flags;
pages = fr->fr_pages;
@@ -920,6 +920,7 @@
newproc = NULL;
vm2 = NULL;
killsx_locked = false;
+ singlethreaded = false;
/*
* Increment the nprocs resource before allocations occur.
@@ -950,14 +951,37 @@
}
/*
- * Atomically check for signals and block threads from sending
- * a signal to our process group until the child is visible.
+ * If we are possibly multi-threaded, and there is a process
+ * sending signal to our group right now, ensure that our
+ * other threads cannot be chosen for the signal queueing.
+ * Otherwise, this might delay signal action, and make the new
+ * child escape the signalling.
*/
pg = p1->p_pgrp;
- if (sx_slock_sig(&pg->pg_killsx) != 0) {
+ if (p1->p_numthreads > 1) {
+ if (sx_try_slock(&pg->pg_killsx) != 0) {
+ killsx_locked = true;
+ } else {
+ PROC_LOCK(p1);
+ if (thread_single(p1, SINGLE_BOUNDARY)) {
+ PROC_UNLOCK(p1);
+ error = ERESTART;
+ goto fail2;
+ }
+ PROC_UNLOCK(p1);
+ singlethreaded = true;
+ }
+ }
+
+ /*
+ * Atomically check for signals and block processes from sending
+ * a signal to our process group until the child is visible.
+ */
+ if (!killsx_locked && sx_slock_sig(&pg->pg_killsx) != 0) {
error = ERESTART;
goto fail2;
- } else if (__predict_false(p1->p_pgrp != pg || sig_intr() != 0)) {
+ }
+ if (__predict_false(p1->p_pgrp != pg || sig_intr() != 0)) {
/*
* Either the process was moved to other process
* group, or there is pending signal. sx_slock_sig()
@@ -1062,8 +1086,8 @@
}
do_fork(td, fr, newproc, td2, vm2, fp_procdesc);
- sx_sunlock(&pg->pg_killsx);
- return (0);
+ error = 0;
+ goto cleanup;
fail0:
error = EAGAIN;
#ifdef MAC
@@ -1081,9 +1105,16 @@
fdrop(fp_procdesc, td);
}
atomic_add_int(&nprocs, -1);
+cleanup:
if (killsx_locked)
sx_sunlock(&pg->pg_killsx);
- pause("fork", hz / 2);
+ if (singlethreaded) {
+ PROC_LOCK(p1);
+ thread_single_end(p1, SINGLE_BOUNDARY);
+ PROC_UNLOCK(p1);
+ }
+ if (error != 0)
+ pause("fork", hz / 2);
return (error);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2158,14 +2158,18 @@
if (curproc == p && !SIGISMEMBER(curthread->td_sigmask, sig) &&
(!fast_sigblock || curthread->td_sigblock_val == 0))
return (curthread);
+
+ /* Find a non-stopped thread that does not mask the signal. */
signal_td = NULL;
FOREACH_THREAD_IN_PROC(p, td) {
if (!SIGISMEMBER(td->td_sigmask, sig) && (!fast_sigblock ||
- td != curthread || td->td_sigblock_val == 0)) {
+ td != curthread || td->td_sigblock_val == 0) &&
+ (td->td_flags & TDF_BOUNDARY) == 0) {
signal_td = td;
break;
}
}
+ /* Select random (first) thread if no better match was found. */
if (signal_td == NULL)
signal_td = FIRST_THREAD_IN_PROC(p);
return (signal_td);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jan 27, 5:24 AM (17 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28050975
Default Alt Text
D41128.id125096.diff (3 KB)
Attached To
Mode
D41128: Different fix for the killpg race, part2
Attached
Detach File
Event Timeline
Log In to Comment