Page MenuHomeFreeBSD

D30675.id90885.diff
No OneTemporary

D30675.id90885.diff

diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -752,7 +752,8 @@
.sv_setregs = linux_exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP,
+ .sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP | SV_SIG_DISCIGN |
+ SV_SIG_WAITNDQ,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = NULL,
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -919,7 +919,8 @@
.sv_setregs = linux_exec_setregs,
.sv_fixlimit = linux32_fixlimit,
.sv_maxssiz = &linux32_maxssiz,
- .sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32 | SV_SHP,
+ .sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32 | SV_SHP |
+ SV_SIG_DISCIGN | SV_SIG_WAITNDQ,
.sv_set_syscall_retval = linux32_set_syscall_retval,
.sv_fetch_syscall_args = linux32_fetch_syscall_args,
.sv_syscallnames = NULL,
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -429,7 +429,8 @@
.sv_setregs = linux_exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP,
+ .sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP | SV_SIG_DISCIGN |
+ SV_SIG_WAITNDQ,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = NULL,
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -859,7 +859,8 @@
.sv_setregs = linux_exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32,
+ .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32 |
+ SV_SIG_IGNIGN | SV_SIG_WAITNDQ,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = NULL,
@@ -897,7 +898,8 @@
.sv_setregs = linux_exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP,
+ .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP |
+ SV_SIG_DISCIGN | SV_SIG_WAITNDQ,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = NULL,
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -105,6 +105,11 @@
&kern_kill_on_dbg_exit, 0,
"Kill ptraced processes when debugger exits");
+static bool kern_wait_dequeue_sigchld = 1;
+SYSCTL_BOOL(_kern, OID_AUTO, wait_dequeue_sigchld, CTLFLAG_RWTUN,
+ &kern_wait_dequeue_sigchld, 0,
+ "Dequeue SIGCHLD on wait(2) for live process");
+
struct proc *
proc_realparent(struct proc *child)
{
@@ -1207,9 +1212,12 @@
p->p_flag &= ~P_CONTINUED;
else
p->p_flag |= P_WAITED;
- PROC_LOCK(td->td_proc);
- sigqueue_take(p->p_ksi);
- PROC_UNLOCK(td->td_proc);
+ if (kern_wait_dequeue_sigchld &&
+ (td->td_proc->p_sysent->sv_flags & SV_SIG_WAITNDQ) == 0) {
+ PROC_LOCK(td->td_proc);
+ sigqueue_take(p->p_ksi);
+ PROC_UNLOCK(td->td_proc);
+ }
}
sx_xunlock(&proctree_lock);
if (siginfo != NULL) {
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
@@ -163,6 +163,12 @@
"Fetch sigfastblock word on each syscall entry for proper "
"blocking semantic");
+static bool kern_sig_discard_ign = true;
+SYSCTL_BOOL(_kern, OID_AUTO, sig_discard_ign, CTLFLAG_RWTUN,
+ &kern_sig_discard_ign, 0,
+ "Discard ignored signals on delivery, otherwise queue them to "
+ "the target queue");
+
SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL);
/*
@@ -1167,10 +1173,15 @@
error = kern_sigtimedwait(td, set, &ksi, NULL);
if (error) {
+ /*
+ * sigwait() function shall not return EINTR, but
+ * the syscall does. Non-ancient libc provides the
+ * wrapper which hides EINTR. Otherwise, EINTR return
+ * is used by libthr to handle required cancellation
+ * point in the sigwait().
+ */
if (error == EINTR && td->td_proc->p_osrel < P_OSREL_SIGWAIT)
- error = ERESTART;
- if (error == ERESTART)
- return (error);
+ return (ERESTART);
td->td_retval[0] = error;
return (0);
}
@@ -1285,6 +1296,9 @@
PROC_LOCK(p);
saved_mask = td->td_sigmask;
SIGSETNAND(td->td_sigmask, waitset);
+ if ((p->p_sysent->sv_flags & SV_SIG_DISCIGN) != 0 ||
+ !kern_sig_discard_ign)
+ td->td_pflags2 |= TDP2_SIGWAIT;
for (;;) {
mtx_lock(&ps->ps_mtx);
sig = cursig(td);
@@ -1329,15 +1343,13 @@
error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", timo);
- if (timeout != NULL) {
- if (error == ERESTART) {
- /* Timeout can not be restarted. */
- error = EINTR;
- } else if (error == EAGAIN) {
- /* We will calculate timeout by ourself. */
- error = 0;
- }
- }
+ /* The syscalls can not be restarted. */
+ if (error == ERESTART)
+ error = EINTR;
+
+ /* We will calculate timeout by ourself. */
+ if (timeout != NULL && error == EAGAIN)
+ error = 0;
/*
* If PTRACE_SCE or PTRACE_SCX were set after
@@ -1349,6 +1361,7 @@
if (error == 0 && (p->p_ptevents & PTRACE_SYSCALL) != 0)
traced = true;
}
+ td->td_pflags2 &= ~TDP2_SIGWAIT;
new_block = saved_mask;
SIGSETNAND(new_block, td->td_sigmask);
@@ -2197,22 +2210,25 @@
SDT_PROBE3(proc, , , signal__send, td, p, sig);
/*
- * If the signal is being ignored,
- * then we forget about it immediately.
- * (Note: we don't set SIGCONT in ps_sigignore,
- * and if it is set to SIG_IGN,
- * action will be SIG_DFL here.)
+ * If the signal is being ignored, then we forget about it
+ * immediately, except when the target process executes
+ * sigwait(). (Note: we don't set SIGCONT in ps_sigignore,
+ * and if it is set to SIG_IGN, action will be SIG_DFL here.)
*/
mtx_lock(&ps->ps_mtx);
if (SIGISMEMBER(ps->ps_sigignore, sig)) {
- SDT_PROBE3(proc, , , signal__discard, td, p, sig);
+ if (kern_sig_discard_ign &&
+ (p->p_sysent->sv_flags & SV_SIG_DISCIGN) == 0) {
+ SDT_PROBE3(proc, , , signal__discard, td, p, sig);
- mtx_unlock(&ps->ps_mtx);
- if (ksi && (ksi->ksi_flags & KSI_INS))
- ksiginfo_tryfree(ksi);
- return (ret);
- }
- if (SIGISMEMBER(td->td_sigmask, sig))
+ mtx_unlock(&ps->ps_mtx);
+ if (ksi && (ksi->ksi_flags & KSI_INS))
+ ksiginfo_tryfree(ksi);
+ return (ret);
+ } else {
+ action = SIG_CATCH;
+ }
+ } else if (SIGISMEMBER(td->td_sigmask, sig))
action = SIG_HOLD;
else if (SIGISMEMBER(ps->ps_sigcatch, sig))
action = SIG_CATCH;
@@ -2947,11 +2963,13 @@
}
/*
- * We should see pending but ignored signals
- * only if P_TRACED was on when they were posted.
+ * We should allow pending but ignored signals below
+ * only if there is sigwait() active, or P_TRACED was
+ * on when they were posted.
*/
if (SIGISMEMBER(ps->ps_sigignore, sig) &&
- (p->p_flag & P_TRACED) == 0) {
+ (p->p_flag & P_TRACED) == 0 &&
+ (td->td_pflags2 & TDP2_SIGWAIT) == 0) {
sigqueue_delete(&td->td_sigqueue, sig);
sigqueue_delete(&p->p_sigqueue, sig);
continue;
@@ -3063,10 +3081,11 @@
PROC_SUNLOCK(p);
mtx_lock(&ps->ps_mtx);
goto next;
- } else if (prop & SIGPROP_IGNORE) {
+ } else if ((prop & SIGPROP_IGNORE) != 0 &&
+ (td->td_pflags2 & TDP2_SIGWAIT) == 0) {
/*
- * Except for SIGCONT, shouldn't get here.
- * Default action is to ignore; drop it.
+ * Default action is to ignore; drop it if
+ * not in kern_sigtimedwait().
*/
break; /* == ignore */
} else
@@ -3074,15 +3093,10 @@
/*NOTREACHED*/
case (intptr_t)SIG_IGN:
- /*
- * Masking above should prevent us ever trying
- * to take action on an ignored signal other
- * than SIGCONT, unless process is traced.
- */
- if ((prop & SIGPROP_CONT) == 0 &&
- (p->p_flag & P_TRACED) == 0)
- printf("issignal\n");
- break; /* == ignore */
+ if ((td->td_pflags2 & TDP2_SIGWAIT) == 0)
+ break; /* == ignore */
+ else
+ return (sig);
default:
/*
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -529,6 +529,7 @@
#define TDP2_SBPAGES 0x00000001 /* Owns sbusy on some pages */
#define TDP2_COMPAT32RB 0x00000002 /* compat32 ABI for robust lists */
#define TDP2_ACCT 0x00000004 /* Doing accounting */
+#define TDP2_SIGWAIT 0x00000008 /* Ignore ignored signals */
/*
* Reasons that the current thread can not be run yet.
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -161,6 +161,8 @@
#define SV_TIMEKEEP 0x040000 /* Shared page timehands. */
#define SV_ASLR 0x080000 /* ASLR allowed. */
#define SV_RNG_SEED_VER 0x100000 /* random(4) reseed generation. */
+#define SV_SIG_DISCIGN 0x200000 /* Do not discard ignored signals */
+#define SV_SIG_WAITNDQ 0x400000 /* Wait does not dequeue SIGCHLD */
#define SV_ABI_MASK 0xff
#define SV_PROC_FLAG(p, x) ((p)->p_sysent->sv_flags & (x))

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 17, 1:23 AM (17 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29800451
Default Alt Text
D30675.id90885.diff (9 KB)

Event Timeline