-/* $OpenBSD: kern_sig.c,v 1.323 2024/03/30 13:33:20 mpi Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.324 2024/04/10 10:05:26 claudio Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
switch (SCARG(uap, how)) {
case SIG_BLOCK:
- atomic_setbits_int(&p->p_sigmask, mask);
+ SET(p->p_sigmask, mask);
break;
case SIG_UNBLOCK:
- atomic_clearbits_int(&p->p_sigmask, mask);
+ CLR(p->p_sigmask, mask);
break;
case SIG_SETMASK:
p->p_sigmask = mask;
KASSERT(p == curproc);
p->p_oldmask = p->p_sigmask;
- atomic_setbits_int(&p->p_flag, P_SIGSUSPEND);
p->p_sigmask = newmask;
+ atomic_setbits_int(&p->p_flag, P_SIGSUSPEND);
}
/*
postsig_done(struct proc *p, int signum, sigset_t catchmask, int reset)
{
p->p_ru.ru_nsignals++;
- atomic_setbits_int(&p->p_sigmask, catchmask);
+ SET(p->p_sigmask, catchmask);
if (reset != 0) {
sigset_t mask = sigmask(signum);
struct sigacts *ps = p->p_p->ps_sigacts;
{
int s, prop;
sig_t action;
- int mask;
+ sigset_t mask, sigmask;
int *siglist;
struct process *pr = p->p_p;
struct proc *q;
return;
mask = sigmask(signum);
+ sigmask = READ_ONCE(p->p_sigmask);
if (type == SPROCESS) {
+ sigset_t tmpmask;
+
/* Accept SIGKILL to coredumping processes */
if (pr->ps_flags & PS_COREDUMP && signum == SIGKILL) {
atomic_setbits_int(&pr->ps_siglist, mask);
* immediately (it's unblocked) then have it take it.
*/
q = curproc;
- if (q != NULL && q->p_p == pr && (q->p_flag & P_WEXIT) == 0 &&
- (q->p_sigmask & mask) == 0)
+ tmpmask = READ_ONCE(q->p_sigmask);
+ if (q->p_p == pr && (q->p_flag & P_WEXIT) == 0 &&
+ (tmpmask & mask) == 0) {
p = q;
- else {
+ sigmask = tmpmask;
+ } else {
/*
* A process-wide signal can be diverted to a
* different thread that's in sigwait() for this
* main thread.
*/
TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) {
+
/* ignore exiting threads */
if (q->p_flag & P_WEXIT)
continue;
/* skip threads that have the signal blocked */
- if ((q->p_sigmask & mask) != 0)
+ tmpmask = READ_ONCE(q->p_sigmask);
+ if ((tmpmask & mask) != 0)
continue;
/* okay, could send to this thread */
p = q;
+ sigmask = tmpmask;
/*
* sigsuspend, sigwait, ppoll/pselect, etc?
if (sigignore & mask)
return;
- if (p->p_sigmask & mask) {
+ if (sigmask & mask) {
action = SIG_HOLD;
} else if (sigcatch & mask) {
action = SIG_CATCH;
*/
if (pr->ps_flags & PS_TRACED)
goto run;
+
+ /*
+ * Recheck sigmask before waking up the process,
+ * there is a chance that while sending the signal
+ * the process changed sigmask and went to sleep.
+ */
+ sigmask = READ_ONCE(p->p_sigmask);
+ if (sigmask & mask)
+ goto out;
+
/*
* If SIGCONT is default (or ignored) and process is
* asleep, we are finished; the process should not
{
struct sigaction sa;
+ KASSERT(p == curproc || panicstr || db_active);
+
memset(&sa, 0, sizeof sa);
sa.sa_handler = SIG_DFL;
setsigvec(p, SIGABRT, &sa);
- atomic_clearbits_int(&p->p_sigmask, sigmask(SIGABRT));
+ CLR(p->p_sigmask, sigmask(SIGABRT));
psignal(p, SIGABRT);
}
struct process *pr = p->p_p;
int rv;
+ KASSERT(p == curproc);
+
mtx_enter(&pr->ps_mtx);
rv = (pr->ps_sigacts->ps_sigignore & sigmask(sig)) ||
(p->p_sigmask & sigmask(sig));
* time for signals to post.
*/
if (p->p_flag & P_SIGSUSPEND) {
- atomic_clearbits_int(&p->p_flag, P_SIGSUSPEND);
p->p_sigmask = p->p_oldmask;
+ atomic_clearbits_int(&p->p_flag, P_SIGSUSPEND);
while ((signum = cursig(p, &ctx)) != 0)
postsig(p, signum, &ctx);
-/* $OpenBSD: sys_generic.c,v 1.156 2023/05/09 14:22:17 visa Exp $ */
+/* $OpenBSD: sys_generic.c,v 1.157 2024/04/10 10:05:26 claudio Exp $ */
/* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */
/*
}
#endif
- if (sigmask) {
- KERNEL_LOCK();
+ if (sigmask)
dosigsuspend(p, *sigmask &~ sigcantmask);
- KERNEL_UNLOCK();
- }
/* Register kqueue events */
error = pselregister(p, pibits, pobits, nd, &nevents, &ncollected);
if ((error = copyin(fds, pl, sz)) != 0)
goto bad;
- if (sigmask) {
- KERNEL_LOCK();
+ if (sigmask)
dosigsuspend(p, *sigmask &~ sigcantmask);
- KERNEL_UNLOCK();
- }
/* Register kqueue events */
ppollregister(p, pl, nfds, &nevents, &ncollected);
-/* $OpenBSD: proc.h,v 1.358 2024/04/02 08:39:16 deraadt Exp $ */
+/* $OpenBSD: proc.h,v 1.359 2024/04/10 10:05:26 claudio Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
* S scheduler lock
* U uidinfolk
* l read only reference, see lim_read_enter()
- * o owned (read/modified only) by this thread
+ * o owned (modified only) by this thread
*/
struct proc {
TAILQ_ENTRY(proc) p_runq; /* [S] current run/sleep queue */
/* The following fields are all copied upon creation in fork. */
#define p_startcopy p_sigmask
- sigset_t p_sigmask; /* [a] Current signal mask */
+ sigset_t p_sigmask; /* [o] Current signal mask */
char p_name[_MAXCOMLEN]; /* thread name, incl NUL */
u_char p_slppri; /* [S] Sleeping priority */
struct user *p_addr; /* Kernel virtual addr of u-area */
struct mdproc p_md; /* Any machine-dependent fields. */
- sigset_t p_oldmask; /* Saved mask from before sigpause */
+ sigset_t p_oldmask; /* [o] Saved mask from before sigpause */
int p_sisig; /* For core dump/debugger XXX */
union sigval p_sigval; /* For core dump/debugger XXX */
long p_sitrapno; /* For core dump/debugger XXX */