1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/bitmap.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/poll_impl.h> /* only needed for kludge in sigwaiting_send() */ 43*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/fault.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/class.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/procset.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/prsystm.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 56*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/bitmap.h> 58*7c478bd9Sstevel@tonic-gate #include <c2/audit.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/core.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/schedctl.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/contract/process_impl.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/dtrace.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/sdt.h> 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* MUST be contiguous */ 66*7c478bd9Sstevel@tonic-gate k_sigset_t nullsmask = {0, 0}; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate k_sigset_t fillset = {FILLSET0, FILLSET1}; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate k_sigset_t cantmask = {CANTMASK0, CANTMASK1}; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate k_sigset_t cantreset = {(sigmask(SIGILL)|sigmask(SIGTRAP)|sigmask(SIGPWR)), 0}; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate k_sigset_t ignoredefault = {(sigmask(SIGCONT)|sigmask(SIGCLD)|sigmask(SIGPWR) 75*7c478bd9Sstevel@tonic-gate |sigmask(SIGWINCH)|sigmask(SIGURG)|sigmask(SIGWAITING)), 76*7c478bd9Sstevel@tonic-gate (sigmask(SIGLWP)|sigmask(SIGCANCEL)|sigmask(SIGFREEZE) 77*7c478bd9Sstevel@tonic-gate |sigmask(SIGTHAW)|sigmask(SIGXRES)|sigmask(SIGJVM1) 78*7c478bd9Sstevel@tonic-gate |sigmask(SIGJVM2))}; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate k_sigset_t stopdefault = {(sigmask(SIGSTOP)|sigmask(SIGTSTP) 81*7c478bd9Sstevel@tonic-gate |sigmask(SIGTTOU)|sigmask(SIGTTIN)), 0}; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate k_sigset_t coredefault = {(sigmask(SIGQUIT)|sigmask(SIGILL)|sigmask(SIGTRAP) 84*7c478bd9Sstevel@tonic-gate |sigmask(SIGIOT)|sigmask(SIGEMT)|sigmask(SIGFPE) 85*7c478bd9Sstevel@tonic-gate |sigmask(SIGBUS)|sigmask(SIGSEGV)|sigmask(SIGSYS) 86*7c478bd9Sstevel@tonic-gate |sigmask(SIGXCPU)|sigmask(SIGXFSZ)), 0}; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate k_sigset_t holdvfork = {(sigmask(SIGTTOU)|sigmask(SIGTTIN)|sigmask(SIGTSTP)), 89*7c478bd9Sstevel@tonic-gate 0}; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate static int isjobstop(int); 92*7c478bd9Sstevel@tonic-gate static void post_sigcld(proc_t *, sigqueue_t *); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * Internal variables for counting number of user thread stop requests posted. 96*7c478bd9Sstevel@tonic-gate * They may not be accurate at some special situation such as that a virtually 97*7c478bd9Sstevel@tonic-gate * stopped thread starts to run. 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate static int num_utstop; 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * Internal variables for broadcasting an event when all thread stop requests 102*7c478bd9Sstevel@tonic-gate * are processed. 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate static kcondvar_t utstop_cv; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate static kmutex_t thread_stop_lock; 107*7c478bd9Sstevel@tonic-gate void del_one_utstop(void); 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * Send the specified signal to the specified process. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate void 113*7c478bd9Sstevel@tonic-gate psignal(proc_t *p, int sig) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 116*7c478bd9Sstevel@tonic-gate sigtoproc(p, NULL, sig); 117*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Send the specified signal to the specified thread. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate void 124*7c478bd9Sstevel@tonic-gate tsignal(kthread_t *t, int sig) 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 129*7c478bd9Sstevel@tonic-gate sigtoproc(p, t, sig); 130*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate int 134*7c478bd9Sstevel@tonic-gate signal_is_blocked(kthread_t *t, int sig) 135*7c478bd9Sstevel@tonic-gate { 136*7c478bd9Sstevel@tonic-gate return (sigismember(&t->t_hold, sig) || 137*7c478bd9Sstevel@tonic-gate (schedctl_sigblock(t) && !sigismember(&cantmask, sig))); 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * Return true if the signal can safely be discarded on generation. 142*7c478bd9Sstevel@tonic-gate * That is, if there is no need for the signal on the receiving end. 143*7c478bd9Sstevel@tonic-gate * The answer is true if the process is a zombie or 144*7c478bd9Sstevel@tonic-gate * if all of these conditions are true: 145*7c478bd9Sstevel@tonic-gate * the signal is being ignored 146*7c478bd9Sstevel@tonic-gate * the process is single-threaded 147*7c478bd9Sstevel@tonic-gate * the signal is not being traced by /proc 148*7c478bd9Sstevel@tonic-gate * the signal is not blocked by the process 149*7c478bd9Sstevel@tonic-gate */ 150*7c478bd9Sstevel@tonic-gate static int 151*7c478bd9Sstevel@tonic-gate sig_discardable(proc_t *p, int sig) 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate kthread_t *t = p->p_tlist; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate return (t == NULL || /* if zombie or ... */ 156*7c478bd9Sstevel@tonic-gate (sigismember(&p->p_ignore, sig) && /* signal is ignored */ 157*7c478bd9Sstevel@tonic-gate t->t_forw == t && /* and single-threaded */ 158*7c478bd9Sstevel@tonic-gate !tracing(p, sig) && /* and no /proc tracing */ 159*7c478bd9Sstevel@tonic-gate !signal_is_blocked(t, sig))); /* and signal not blocked */ 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate /* 163*7c478bd9Sstevel@tonic-gate * Return true if this thread is going to eat this signal soon. 164*7c478bd9Sstevel@tonic-gate */ 165*7c478bd9Sstevel@tonic-gate int 166*7c478bd9Sstevel@tonic-gate eat_signal(kthread_t *t, int sig) 167*7c478bd9Sstevel@tonic-gate { 168*7c478bd9Sstevel@tonic-gate int rval = 0; 169*7c478bd9Sstevel@tonic-gate ASSERT(THREAD_LOCK_HELD(t)); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Do not do anything if the target thread has the signal blocked. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate if (!signal_is_blocked(t, sig)) { 175*7c478bd9Sstevel@tonic-gate t->t_sig_check = 1; /* have thread do an issig */ 176*7c478bd9Sstevel@tonic-gate if (t->t_state == TS_SLEEP && (t->t_flag & T_WAKEABLE)) { 177*7c478bd9Sstevel@tonic-gate setrun_locked(t); 178*7c478bd9Sstevel@tonic-gate rval = 1; 179*7c478bd9Sstevel@tonic-gate } else if (t->t_state == TS_STOPPED && sig == SIGKILL) { 180*7c478bd9Sstevel@tonic-gate ttoproc(t)->p_stopsig = 0; 181*7c478bd9Sstevel@tonic-gate t->t_dtrace_stop = 0; 182*7c478bd9Sstevel@tonic-gate t->t_schedflag |= TS_XSTART | TS_PSTART; 183*7c478bd9Sstevel@tonic-gate setrun_locked(t); 184*7c478bd9Sstevel@tonic-gate } else if (t != curthread && t->t_state == TS_ONPROC) { 185*7c478bd9Sstevel@tonic-gate if ((t != curthread) && (t->t_cpu != CPU)) 186*7c478bd9Sstevel@tonic-gate poke_cpu(t->t_cpu->cpu_id); 187*7c478bd9Sstevel@tonic-gate rval = 1; 188*7c478bd9Sstevel@tonic-gate } else if (t->t_state == TS_RUN) { 189*7c478bd9Sstevel@tonic-gate rval = 1; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate return (rval); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * Post a signal. 198*7c478bd9Sstevel@tonic-gate * If a non-null thread pointer is passed, then post the signal 199*7c478bd9Sstevel@tonic-gate * to the thread/lwp, otherwise post the signal to the process. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate void 202*7c478bd9Sstevel@tonic-gate sigtoproc(proc_t *p, kthread_t *t, int sig) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate kthread_t *tt; 205*7c478bd9Sstevel@tonic-gate int ext = !(curproc->p_flag & SSYS) && 206*7c478bd9Sstevel@tonic-gate (curproc->p_ct_process != p->p_ct_process); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate if (sig <= 0 || sig >= NSIG) 211*7c478bd9Sstevel@tonic-gate return; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * Regardless of origin or directedness, 215*7c478bd9Sstevel@tonic-gate * SIGKILL kills all lwps in the process immediately 216*7c478bd9Sstevel@tonic-gate * and jobcontrol signals affect all lwps in the process. 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate if (sig == SIGKILL) { 219*7c478bd9Sstevel@tonic-gate p->p_flag |= SKILLED | (ext ? SEXTKILLED : 0); 220*7c478bd9Sstevel@tonic-gate t = NULL; 221*7c478bd9Sstevel@tonic-gate } else if (sig == SIGCONT) { 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * The SSCONT flag will remain set until a stopping 224*7c478bd9Sstevel@tonic-gate * signal comes in (below). This is harmless. 225*7c478bd9Sstevel@tonic-gate */ 226*7c478bd9Sstevel@tonic-gate p->p_flag |= SSCONT; 227*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, SIGSTOP); 228*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, SIGTSTP); 229*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, SIGTTOU); 230*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, SIGTTIN); 231*7c478bd9Sstevel@tonic-gate sigdiffset(&p->p_sig, &stopdefault); 232*7c478bd9Sstevel@tonic-gate sigdiffset(&p->p_extsig, &stopdefault); 233*7c478bd9Sstevel@tonic-gate p->p_stopsig = 0; 234*7c478bd9Sstevel@tonic-gate if ((tt = p->p_tlist) != NULL) { 235*7c478bd9Sstevel@tonic-gate do { 236*7c478bd9Sstevel@tonic-gate sigdelq(p, tt, SIGSTOP); 237*7c478bd9Sstevel@tonic-gate sigdelq(p, tt, SIGTSTP); 238*7c478bd9Sstevel@tonic-gate sigdelq(p, tt, SIGTTOU); 239*7c478bd9Sstevel@tonic-gate sigdelq(p, tt, SIGTTIN); 240*7c478bd9Sstevel@tonic-gate sigdiffset(&tt->t_sig, &stopdefault); 241*7c478bd9Sstevel@tonic-gate sigdiffset(&tt->t_extsig, &stopdefault); 242*7c478bd9Sstevel@tonic-gate } while ((tt = tt->t_forw) != p->p_tlist); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate if ((tt = p->p_tlist) != NULL) { 245*7c478bd9Sstevel@tonic-gate do { 246*7c478bd9Sstevel@tonic-gate thread_lock(tt); 247*7c478bd9Sstevel@tonic-gate if (tt->t_state == TS_STOPPED && 248*7c478bd9Sstevel@tonic-gate tt->t_whystop == PR_JOBCONTROL) { 249*7c478bd9Sstevel@tonic-gate tt->t_schedflag |= TS_XSTART; 250*7c478bd9Sstevel@tonic-gate setrun_locked(tt); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate thread_unlock(tt); 253*7c478bd9Sstevel@tonic-gate } while ((tt = tt->t_forw) != p->p_tlist); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate } else if (sigismember(&stopdefault, sig)) { 256*7c478bd9Sstevel@tonic-gate /* 257*7c478bd9Sstevel@tonic-gate * This test has a race condition which we can't fix: 258*7c478bd9Sstevel@tonic-gate * By the time the stopping signal is received by 259*7c478bd9Sstevel@tonic-gate * the target process/thread, the signal handler 260*7c478bd9Sstevel@tonic-gate * and/or the detached state might have changed. 261*7c478bd9Sstevel@tonic-gate */ 262*7c478bd9Sstevel@tonic-gate if (PTOU(p)->u_signal[sig-1] == SIG_DFL && 263*7c478bd9Sstevel@tonic-gate (sig == SIGSTOP || !p->p_pgidp->pid_pgorphaned)) 264*7c478bd9Sstevel@tonic-gate p->p_flag &= ~SSCONT; 265*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, SIGCONT); 266*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_sig, SIGCONT); 267*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_extsig, SIGCONT); 268*7c478bd9Sstevel@tonic-gate if ((tt = p->p_tlist) != NULL) { 269*7c478bd9Sstevel@tonic-gate do { 270*7c478bd9Sstevel@tonic-gate sigdelq(p, tt, SIGCONT); 271*7c478bd9Sstevel@tonic-gate sigdelset(&tt->t_sig, SIGCONT); 272*7c478bd9Sstevel@tonic-gate sigdelset(&tt->t_extsig, SIGCONT); 273*7c478bd9Sstevel@tonic-gate } while ((tt = tt->t_forw) != p->p_tlist); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate if (sig_discardable(p, sig)) { 278*7c478bd9Sstevel@tonic-gate DTRACE_PROC3(signal__discard, kthread_t *, p->p_tlist, 279*7c478bd9Sstevel@tonic-gate proc_t *, p, int, sig); 280*7c478bd9Sstevel@tonic-gate return; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate if (t != NULL) { 284*7c478bd9Sstevel@tonic-gate /* 285*7c478bd9Sstevel@tonic-gate * This is a directed signal, wake up the lwp. 286*7c478bd9Sstevel@tonic-gate */ 287*7c478bd9Sstevel@tonic-gate sigaddset(&t->t_sig, sig); 288*7c478bd9Sstevel@tonic-gate if (ext) 289*7c478bd9Sstevel@tonic-gate sigaddset(&t->t_extsig, sig); 290*7c478bd9Sstevel@tonic-gate thread_lock(t); 291*7c478bd9Sstevel@tonic-gate (void) eat_signal(t, sig); 292*7c478bd9Sstevel@tonic-gate thread_unlock(t); 293*7c478bd9Sstevel@tonic-gate DTRACE_PROC2(signal__send, kthread_t *, t, int, sig); 294*7c478bd9Sstevel@tonic-gate } else if ((tt = p->p_tlist) != NULL) { 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * Make sure that some lwp that already exists 297*7c478bd9Sstevel@tonic-gate * in the process fields the signal soon. 298*7c478bd9Sstevel@tonic-gate * Wake up an interruptibly sleeping lwp if necessary. 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate int su = 0; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate sigaddset(&p->p_sig, sig); 303*7c478bd9Sstevel@tonic-gate if (ext) 304*7c478bd9Sstevel@tonic-gate sigaddset(&p->p_extsig, sig); 305*7c478bd9Sstevel@tonic-gate do { 306*7c478bd9Sstevel@tonic-gate thread_lock(tt); 307*7c478bd9Sstevel@tonic-gate if (eat_signal(tt, sig)) { 308*7c478bd9Sstevel@tonic-gate thread_unlock(tt); 309*7c478bd9Sstevel@tonic-gate break; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate if (sig == SIGKILL && SUSPENDED(tt)) 312*7c478bd9Sstevel@tonic-gate su++; 313*7c478bd9Sstevel@tonic-gate thread_unlock(tt); 314*7c478bd9Sstevel@tonic-gate } while ((tt = tt->t_forw) != p->p_tlist); 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * If the process is deadlocked, make somebody run and die. 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate if (sig == SIGKILL && p->p_stat != SIDL && 319*7c478bd9Sstevel@tonic-gate p->p_lwprcnt == 0 && p->p_lwpcnt == su) { 320*7c478bd9Sstevel@tonic-gate thread_lock(tt); 321*7c478bd9Sstevel@tonic-gate p->p_lwprcnt++; 322*7c478bd9Sstevel@tonic-gate tt->t_schedflag |= TS_CSTART; 323*7c478bd9Sstevel@tonic-gate setrun_locked(tt); 324*7c478bd9Sstevel@tonic-gate thread_unlock(tt); 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate DTRACE_PROC2(signal__send, kthread_t *, tt, int, sig); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate static int 332*7c478bd9Sstevel@tonic-gate isjobstop(int sig) 333*7c478bd9Sstevel@tonic-gate { 334*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (u.u_signal[sig-1] == SIG_DFL && sigismember(&stopdefault, sig)) { 339*7c478bd9Sstevel@tonic-gate /* 340*7c478bd9Sstevel@tonic-gate * If SIGCONT has been posted since we promoted this signal 341*7c478bd9Sstevel@tonic-gate * from pending to current, then don't do a jobcontrol stop. 342*7c478bd9Sstevel@tonic-gate */ 343*7c478bd9Sstevel@tonic-gate if (!(p->p_flag & SSCONT) && 344*7c478bd9Sstevel@tonic-gate (sig == SIGSTOP || !p->p_pgidp->pid_pgorphaned) && 345*7c478bd9Sstevel@tonic-gate curthread != p->p_agenttp) { 346*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate stop(PR_JOBCONTROL, sig); 349*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 350*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); 351*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Only the first lwp to continue notifies the parent. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate if (p->p_pidflag & CLDCONT) 356*7c478bd9Sstevel@tonic-gate siginfofree(sqp); 357*7c478bd9Sstevel@tonic-gate else { 358*7c478bd9Sstevel@tonic-gate p->p_pidflag |= CLDCONT; 359*7c478bd9Sstevel@tonic-gate p->p_wcode = CLD_CONTINUED; 360*7c478bd9Sstevel@tonic-gate p->p_wdata = SIGCONT; 361*7c478bd9Sstevel@tonic-gate sigcld(p, sqp); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 364*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate return (1); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate return (0); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Returns true if the current process has a signal to process, and 373*7c478bd9Sstevel@tonic-gate * the signal is not held. The signal to process is put in p_cursig. 374*7c478bd9Sstevel@tonic-gate * This is asked at least once each time a process enters the system 375*7c478bd9Sstevel@tonic-gate * (though this can usually be done without actually calling issig by 376*7c478bd9Sstevel@tonic-gate * checking the pending signal masks). A signal does not do anything 377*7c478bd9Sstevel@tonic-gate * directly to a process; it sets a flag that asks the process to do 378*7c478bd9Sstevel@tonic-gate * something to itself. 379*7c478bd9Sstevel@tonic-gate * 380*7c478bd9Sstevel@tonic-gate * The "why" argument indicates the allowable side-effects of the call: 381*7c478bd9Sstevel@tonic-gate * 382*7c478bd9Sstevel@tonic-gate * FORREAL: Extract the next pending signal from p_sig into p_cursig; 383*7c478bd9Sstevel@tonic-gate * stop the process if a stop has been requested or if a traced signal 384*7c478bd9Sstevel@tonic-gate * is pending. 385*7c478bd9Sstevel@tonic-gate * 386*7c478bd9Sstevel@tonic-gate * JUSTLOOKING: Don't stop the process, just indicate whether or not 387*7c478bd9Sstevel@tonic-gate * a signal might be pending (FORREAL is needed to tell for sure). 388*7c478bd9Sstevel@tonic-gate * 389*7c478bd9Sstevel@tonic-gate * XXX: Changes to the logic in these routines should be propagated 390*7c478bd9Sstevel@tonic-gate * to lm_sigispending(). See bug 1201594. 391*7c478bd9Sstevel@tonic-gate */ 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate static int issig_forreal(void); 394*7c478bd9Sstevel@tonic-gate static int issig_justlooking(void); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate int 397*7c478bd9Sstevel@tonic-gate issig(int why) 398*7c478bd9Sstevel@tonic-gate { 399*7c478bd9Sstevel@tonic-gate ASSERT(why == FORREAL || why == JUSTLOOKING); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate return ((why == FORREAL)? issig_forreal() : issig_justlooking()); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate static int 406*7c478bd9Sstevel@tonic-gate issig_justlooking(void) 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 409*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 410*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 411*7c478bd9Sstevel@tonic-gate k_sigset_t set; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* 414*7c478bd9Sstevel@tonic-gate * This function answers the question: 415*7c478bd9Sstevel@tonic-gate * "Is there any reason to call issig_forreal()?" 416*7c478bd9Sstevel@tonic-gate * 417*7c478bd9Sstevel@tonic-gate * We have to answer the question w/o grabbing any locks 418*7c478bd9Sstevel@tonic-gate * because we are (most likely) being called after we 419*7c478bd9Sstevel@tonic-gate * put ourselves on the sleep queue. 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (t->t_dtrace_stop | t->t_dtrace_sig) 423*7c478bd9Sstevel@tonic-gate return (1); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* 426*7c478bd9Sstevel@tonic-gate * Another piece of complexity in this process. When single-stepping a 427*7c478bd9Sstevel@tonic-gate * process, we don't want an intervening signal or TP_PAUSE request to 428*7c478bd9Sstevel@tonic-gate * suspend the current thread. Otherwise, the controlling process will 429*7c478bd9Sstevel@tonic-gate * hang beacuse we will be stopped with TS_PSTART set in t_schedflag. 430*7c478bd9Sstevel@tonic-gate * We will trigger any remaining signals when we re-enter the kernel on 431*7c478bd9Sstevel@tonic-gate * the single step trap. 432*7c478bd9Sstevel@tonic-gate */ 433*7c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & NORMAL_STEP) 434*7c478bd9Sstevel@tonic-gate return (0); 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if ((lwp->lwp_asleep && MUSTRETURN(p, t)) || 437*7c478bd9Sstevel@tonic-gate (p->p_flag & (SEXITLWPS|SKILLED)) || 438*7c478bd9Sstevel@tonic-gate (lwp->lwp_nostop == 0 && 439*7c478bd9Sstevel@tonic-gate (p->p_stopsig | (p->p_flag & (SHOLDFORK1|SHOLDWATCH)) | 440*7c478bd9Sstevel@tonic-gate (t->t_proc_flag & 441*7c478bd9Sstevel@tonic-gate (TP_PRSTOP|TP_HOLDLWP|TP_CHKPT|TP_PAUSE)))) || 442*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig) 443*7c478bd9Sstevel@tonic-gate return (1); 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate if (p->p_flag & SVFWAIT) 446*7c478bd9Sstevel@tonic-gate return (0); 447*7c478bd9Sstevel@tonic-gate set = p->p_sig; 448*7c478bd9Sstevel@tonic-gate sigorset(&set, &t->t_sig); 449*7c478bd9Sstevel@tonic-gate if (schedctl_sigblock(t)) /* all blockable signals blocked */ 450*7c478bd9Sstevel@tonic-gate sigandset(&set, &cantmask); 451*7c478bd9Sstevel@tonic-gate else 452*7c478bd9Sstevel@tonic-gate sigdiffset(&set, &t->t_hold); 453*7c478bd9Sstevel@tonic-gate if (p->p_flag & SVFORK) 454*7c478bd9Sstevel@tonic-gate sigdiffset(&set, &holdvfork); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate if (!sigisempty(&set)) { 457*7c478bd9Sstevel@tonic-gate int sig; 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate for (sig = 1; sig < NSIG; sig++) { 460*7c478bd9Sstevel@tonic-gate if (sigismember(&set, sig) && 461*7c478bd9Sstevel@tonic-gate (tracing(p, sig) || 462*7c478bd9Sstevel@tonic-gate !sigismember(&p->p_ignore, sig))) { 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate * Don't promote a signal that will stop 465*7c478bd9Sstevel@tonic-gate * the process when lwp_nostop is set. 466*7c478bd9Sstevel@tonic-gate */ 467*7c478bd9Sstevel@tonic-gate if (!lwp->lwp_nostop || 468*7c478bd9Sstevel@tonic-gate u.u_signal[sig-1] != SIG_DFL || 469*7c478bd9Sstevel@tonic-gate !sigismember(&stopdefault, sig)) 470*7c478bd9Sstevel@tonic-gate return (1); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate return (0); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate static int 479*7c478bd9Sstevel@tonic-gate issig_forreal(void) 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate int sig = 0, ext = 0; 482*7c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 483*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 484*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 485*7c478bd9Sstevel@tonic-gate int toproc = 0; 486*7c478bd9Sstevel@tonic-gate int sigcld_found = 0; 487*7c478bd9Sstevel@tonic-gate int nostop_break = 0; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate ASSERT(t->t_state == TS_ONPROC); 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 492*7c478bd9Sstevel@tonic-gate schedctl_finish_sigblock(t); 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate if (t->t_dtrace_stop | t->t_dtrace_sig) { 495*7c478bd9Sstevel@tonic-gate if (t->t_dtrace_stop) { 496*7c478bd9Sstevel@tonic-gate /* 497*7c478bd9Sstevel@tonic-gate * If DTrace's "stop" action has been invoked on us, 498*7c478bd9Sstevel@tonic-gate * set TP_PRSTOP. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate t->t_proc_flag |= TP_PRSTOP; 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate if (t->t_dtrace_sig != 0) { 504*7c478bd9Sstevel@tonic-gate k_siginfo_t info; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* 507*7c478bd9Sstevel@tonic-gate * Post the signal generated as the result of 508*7c478bd9Sstevel@tonic-gate * DTrace's "raise" action as a normal signal before 509*7c478bd9Sstevel@tonic-gate * the full-fledged signal checking begins. 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate bzero(&info, sizeof (info)); 512*7c478bd9Sstevel@tonic-gate info.si_signo = t->t_dtrace_sig; 513*7c478bd9Sstevel@tonic-gate info.si_code = SI_DTRACE; 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate sigaddq(p, NULL, &info, KM_NOSLEEP); 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate t->t_dtrace_sig = 0; 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate for (;;) { 522*7c478bd9Sstevel@tonic-gate if (p->p_flag & (SEXITLWPS|SKILLED)) { 523*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = sig = SIGKILL; 524*7c478bd9Sstevel@tonic-gate lwp->lwp_extsig = ext = (p->p_flag & SEXTKILLED) != 0; 525*7c478bd9Sstevel@tonic-gate break; 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * Another piece of complexity in this process. When 530*7c478bd9Sstevel@tonic-gate * single-stepping a process, we don't want an intervening 531*7c478bd9Sstevel@tonic-gate * signal or TP_PAUSE request to suspend the current thread. 532*7c478bd9Sstevel@tonic-gate * Otherwise, the controlling process will hang beacuse we will 533*7c478bd9Sstevel@tonic-gate * be stopped with TS_PSTART set in t_schedflag. We will 534*7c478bd9Sstevel@tonic-gate * trigger any remaining signals when we re-enter the kernel on 535*7c478bd9Sstevel@tonic-gate * the single step trap. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & NORMAL_STEP) { 538*7c478bd9Sstevel@tonic-gate sig = 0; 539*7c478bd9Sstevel@tonic-gate break; 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate /* 543*7c478bd9Sstevel@tonic-gate * Hold the lwp here for watchpoint manipulation. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate if ((t->t_proc_flag & TP_PAUSE) && !lwp->lwp_nostop) { 546*7c478bd9Sstevel@tonic-gate stop(PR_SUSPENDED, SUSPEND_PAUSE); 547*7c478bd9Sstevel@tonic-gate continue; 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate if (lwp->lwp_asleep && MUSTRETURN(p, t)) { 551*7c478bd9Sstevel@tonic-gate if ((sig = lwp->lwp_cursig) != 0) { 552*7c478bd9Sstevel@tonic-gate /* 553*7c478bd9Sstevel@tonic-gate * Make sure we call ISSIG() in post_syscall() 554*7c478bd9Sstevel@tonic-gate * to re-validate this current signal. 555*7c478bd9Sstevel@tonic-gate */ 556*7c478bd9Sstevel@tonic-gate t->t_sig_check = 1; 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate break; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate /* 562*7c478bd9Sstevel@tonic-gate * If the request is PR_CHECKPOINT, ignore the rest of signals 563*7c478bd9Sstevel@tonic-gate * or requests. Honor other stop requests or signals later. 564*7c478bd9Sstevel@tonic-gate * Go back to top of loop here to check if an exit or hold 565*7c478bd9Sstevel@tonic-gate * event has occurred while stopped. 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate if ((t->t_proc_flag & TP_CHKPT) && !lwp->lwp_nostop) { 568*7c478bd9Sstevel@tonic-gate stop(PR_CHECKPOINT, 0); 569*7c478bd9Sstevel@tonic-gate continue; 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * Honor SHOLDFORK1, SHOLDWATCH, and TP_HOLDLWP before dealing 574*7c478bd9Sstevel@tonic-gate * with signals or /proc. Another lwp is executing fork1(), 575*7c478bd9Sstevel@tonic-gate * or is undergoing watchpoint activity (remapping a page), 576*7c478bd9Sstevel@tonic-gate * or is executing lwp_suspend() on this lwp. 577*7c478bd9Sstevel@tonic-gate * Again, go back to top of loop to check if an exit 578*7c478bd9Sstevel@tonic-gate * or hold event has occurred while stopped. 579*7c478bd9Sstevel@tonic-gate */ 580*7c478bd9Sstevel@tonic-gate if (((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) || 581*7c478bd9Sstevel@tonic-gate (t->t_proc_flag & TP_HOLDLWP)) && !lwp->lwp_nostop) { 582*7c478bd9Sstevel@tonic-gate stop(PR_SUSPENDED, SUSPEND_NORMAL); 583*7c478bd9Sstevel@tonic-gate continue; 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate /* 587*7c478bd9Sstevel@tonic-gate * Honor requested stop before dealing with the 588*7c478bd9Sstevel@tonic-gate * current signal; a debugger may change it. 589*7c478bd9Sstevel@tonic-gate * Do not want to go back to loop here since this is a special 590*7c478bd9Sstevel@tonic-gate * stop that means: make incremental progress before the next 591*7c478bd9Sstevel@tonic-gate * stop. The danger is that returning to top of loop would most 592*7c478bd9Sstevel@tonic-gate * likely drop the thread right back here to stop soon after it 593*7c478bd9Sstevel@tonic-gate * was continued, violating the incremental progress request. 594*7c478bd9Sstevel@tonic-gate */ 595*7c478bd9Sstevel@tonic-gate if ((t->t_proc_flag & TP_PRSTOP) && !lwp->lwp_nostop) 596*7c478bd9Sstevel@tonic-gate stop(PR_REQUESTED, 0); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * If a debugger wants us to take a signal it will have 600*7c478bd9Sstevel@tonic-gate * left it in lwp->lwp_cursig. If lwp_cursig has been cleared 601*7c478bd9Sstevel@tonic-gate * or if it's being ignored, we continue on looking for another 602*7c478bd9Sstevel@tonic-gate * signal. Otherwise we return the specified signal, provided 603*7c478bd9Sstevel@tonic-gate * it's not a signal that causes a job control stop. 604*7c478bd9Sstevel@tonic-gate * 605*7c478bd9Sstevel@tonic-gate * When stopped on PR_JOBCONTROL, there is no current 606*7c478bd9Sstevel@tonic-gate * signal; we cancel lwp->lwp_cursig temporarily before 607*7c478bd9Sstevel@tonic-gate * calling isjobstop(). The current signal may be reset 608*7c478bd9Sstevel@tonic-gate * by a debugger while we are stopped in isjobstop(). 609*7c478bd9Sstevel@tonic-gate */ 610*7c478bd9Sstevel@tonic-gate if ((sig = lwp->lwp_cursig) != 0) { 611*7c478bd9Sstevel@tonic-gate ext = lwp->lwp_extsig; 612*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = 0; 613*7c478bd9Sstevel@tonic-gate lwp->lwp_extsig = 0; 614*7c478bd9Sstevel@tonic-gate if (!sigismember(&p->p_ignore, sig) && 615*7c478bd9Sstevel@tonic-gate !isjobstop(sig)) { 616*7c478bd9Sstevel@tonic-gate if (p->p_flag & (SEXITLWPS|SKILLED)) { 617*7c478bd9Sstevel@tonic-gate sig = SIGKILL; 618*7c478bd9Sstevel@tonic-gate ext = (p->p_flag & SEXTKILLED) != 0; 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = (uchar_t)sig; 621*7c478bd9Sstevel@tonic-gate lwp->lwp_extsig = (uchar_t)ext; 622*7c478bd9Sstevel@tonic-gate break; 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate /* 625*7c478bd9Sstevel@tonic-gate * The signal is being ignored or it caused a 626*7c478bd9Sstevel@tonic-gate * job-control stop. If another current signal 627*7c478bd9Sstevel@tonic-gate * has not been established, return the current 628*7c478bd9Sstevel@tonic-gate * siginfo, if any, to the memory manager. 629*7c478bd9Sstevel@tonic-gate */ 630*7c478bd9Sstevel@tonic-gate if (lwp->lwp_cursig == 0 && lwp->lwp_curinfo != NULL) { 631*7c478bd9Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo); 632*7c478bd9Sstevel@tonic-gate lwp->lwp_curinfo = NULL; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate /* 635*7c478bd9Sstevel@tonic-gate * Loop around again in case we were stopped 636*7c478bd9Sstevel@tonic-gate * on a job control signal and a /proc stop 637*7c478bd9Sstevel@tonic-gate * request was posted or another current signal 638*7c478bd9Sstevel@tonic-gate * was established while we were stopped. 639*7c478bd9Sstevel@tonic-gate */ 640*7c478bd9Sstevel@tonic-gate continue; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate if (p->p_stopsig && !lwp->lwp_nostop && 644*7c478bd9Sstevel@tonic-gate curthread != p->p_agenttp) { 645*7c478bd9Sstevel@tonic-gate /* 646*7c478bd9Sstevel@tonic-gate * Some lwp in the process has already stopped 647*7c478bd9Sstevel@tonic-gate * showing PR_JOBCONTROL. This is a stop in 648*7c478bd9Sstevel@tonic-gate * sympathy with the other lwp, even if this 649*7c478bd9Sstevel@tonic-gate * lwp is blocking the stopping signal. 650*7c478bd9Sstevel@tonic-gate */ 651*7c478bd9Sstevel@tonic-gate stop(PR_JOBCONTROL, p->p_stopsig); 652*7c478bd9Sstevel@tonic-gate continue; 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* 656*7c478bd9Sstevel@tonic-gate * Loop on the pending signals until we find a 657*7c478bd9Sstevel@tonic-gate * non-held signal that is traced or not ignored. 658*7c478bd9Sstevel@tonic-gate * First check the signals pending for the lwp, 659*7c478bd9Sstevel@tonic-gate * then the signals pending for the process as a whole. 660*7c478bd9Sstevel@tonic-gate */ 661*7c478bd9Sstevel@tonic-gate for (;;) { 662*7c478bd9Sstevel@tonic-gate k_sigset_t tsig; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate tsig = t->t_sig; 665*7c478bd9Sstevel@tonic-gate if ((sig = fsig(&tsig, t)) != 0) { 666*7c478bd9Sstevel@tonic-gate if (sig == SIGCLD) 667*7c478bd9Sstevel@tonic-gate sigcld_found = 1; 668*7c478bd9Sstevel@tonic-gate toproc = 0; 669*7c478bd9Sstevel@tonic-gate if (tracing(p, sig) || 670*7c478bd9Sstevel@tonic-gate !sigismember(&p->p_ignore, sig)) { 671*7c478bd9Sstevel@tonic-gate if (sigismember(&t->t_extsig, sig)) 672*7c478bd9Sstevel@tonic-gate ext = 1; 673*7c478bd9Sstevel@tonic-gate break; 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate sigdelset(&t->t_sig, sig); 676*7c478bd9Sstevel@tonic-gate sigdelset(&t->t_extsig, sig); 677*7c478bd9Sstevel@tonic-gate sigdelq(p, t, sig); 678*7c478bd9Sstevel@tonic-gate } else if ((sig = fsig(&p->p_sig, t)) != 0) { 679*7c478bd9Sstevel@tonic-gate if (sig == SIGCLD) 680*7c478bd9Sstevel@tonic-gate sigcld_found = 1; 681*7c478bd9Sstevel@tonic-gate toproc = 1; 682*7c478bd9Sstevel@tonic-gate if (tracing(p, sig) || 683*7c478bd9Sstevel@tonic-gate !sigismember(&p->p_ignore, sig)) { 684*7c478bd9Sstevel@tonic-gate if (sigismember(&p->p_extsig, sig)) 685*7c478bd9Sstevel@tonic-gate ext = 1; 686*7c478bd9Sstevel@tonic-gate break; 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_sig, sig); 689*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_extsig, sig); 690*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, sig); 691*7c478bd9Sstevel@tonic-gate } else { 692*7c478bd9Sstevel@tonic-gate /* no signal was found */ 693*7c478bd9Sstevel@tonic-gate break; 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate if (sig == 0) { /* no signal was found */ 698*7c478bd9Sstevel@tonic-gate if (p->p_flag & (SEXITLWPS|SKILLED)) { 699*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = SIGKILL; 700*7c478bd9Sstevel@tonic-gate sig = SIGKILL; 701*7c478bd9Sstevel@tonic-gate ext = (p->p_flag & SEXTKILLED) != 0; 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate break; 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate /* 707*7c478bd9Sstevel@tonic-gate * If we have been informed not to stop (i.e., we are being 708*7c478bd9Sstevel@tonic-gate * called from within a network operation), then don't promote 709*7c478bd9Sstevel@tonic-gate * the signal at this time, just return the signal number. 710*7c478bd9Sstevel@tonic-gate * We will call issig() again later when it is safe. 711*7c478bd9Sstevel@tonic-gate * 712*7c478bd9Sstevel@tonic-gate * fsig() does not return a jobcontrol stopping signal 713*7c478bd9Sstevel@tonic-gate * with a default action of stopping the process if 714*7c478bd9Sstevel@tonic-gate * lwp_nostop is set, so we won't be causing a bogus 715*7c478bd9Sstevel@tonic-gate * EINTR by this action. (Such a signal is eaten by 716*7c478bd9Sstevel@tonic-gate * isjobstop() when we loop around to do final checks.) 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate if (lwp->lwp_nostop) { 719*7c478bd9Sstevel@tonic-gate nostop_break = 1; 720*7c478bd9Sstevel@tonic-gate break; 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate /* 724*7c478bd9Sstevel@tonic-gate * Promote the signal from pending to current. 725*7c478bd9Sstevel@tonic-gate * 726*7c478bd9Sstevel@tonic-gate * Note that sigdeq() will set lwp->lwp_curinfo to NULL 727*7c478bd9Sstevel@tonic-gate * if no siginfo_t exists for this signal. 728*7c478bd9Sstevel@tonic-gate */ 729*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = (uchar_t)sig; 730*7c478bd9Sstevel@tonic-gate lwp->lwp_extsig = (uchar_t)ext; 731*7c478bd9Sstevel@tonic-gate t->t_sig_check = 1; /* so post_syscall will see signal */ 732*7c478bd9Sstevel@tonic-gate ASSERT(lwp->lwp_curinfo == NULL); 733*7c478bd9Sstevel@tonic-gate sigdeq(p, toproc ? NULL : t, sig, &lwp->lwp_curinfo); 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate if (tracing(p, sig)) 736*7c478bd9Sstevel@tonic-gate stop(PR_SIGNALLED, sig); 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate /* 739*7c478bd9Sstevel@tonic-gate * Loop around to check for requested stop before 740*7c478bd9Sstevel@tonic-gate * performing the usual current-signal actions. 741*7c478bd9Sstevel@tonic-gate */ 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* 747*7c478bd9Sstevel@tonic-gate * If SIGCLD was dequeued, search for other pending SIGCLD's. 748*7c478bd9Sstevel@tonic-gate * Don't do it if we are returning SIGCLD and the signal 749*7c478bd9Sstevel@tonic-gate * handler will be reset by psig(); this enables reliable 750*7c478bd9Sstevel@tonic-gate * delivery of SIGCLD even when using the old, broken 751*7c478bd9Sstevel@tonic-gate * signal() interface for setting the signal handler. 752*7c478bd9Sstevel@tonic-gate */ 753*7c478bd9Sstevel@tonic-gate if (sigcld_found && 754*7c478bd9Sstevel@tonic-gate (sig != SIGCLD || !sigismember(&u.u_sigresethand, SIGCLD))) 755*7c478bd9Sstevel@tonic-gate sigcld_repost(); 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate if (sig != 0) 758*7c478bd9Sstevel@tonic-gate (void) undo_watch_step(NULL); 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate /* 761*7c478bd9Sstevel@tonic-gate * If we have been blocked since the p_lock was dropped off 762*7c478bd9Sstevel@tonic-gate * above, then this promoted signal might have been handled 763*7c478bd9Sstevel@tonic-gate * already when we were on the way back from sleep queue, so 764*7c478bd9Sstevel@tonic-gate * just ignore it. 765*7c478bd9Sstevel@tonic-gate * If we have been informed not to stop, just return the signal 766*7c478bd9Sstevel@tonic-gate * number. Also see comments above. 767*7c478bd9Sstevel@tonic-gate */ 768*7c478bd9Sstevel@tonic-gate if (!nostop_break) { 769*7c478bd9Sstevel@tonic-gate sig = lwp->lwp_cursig; 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate return (sig != 0); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate /* 776*7c478bd9Sstevel@tonic-gate * Return true if the process is currently stopped showing PR_JOBCONTROL. 777*7c478bd9Sstevel@tonic-gate * This is true only if all of the process's lwp's are so stopped. 778*7c478bd9Sstevel@tonic-gate * If this is asked by one of the lwps in the process, exclude that lwp. 779*7c478bd9Sstevel@tonic-gate */ 780*7c478bd9Sstevel@tonic-gate int 781*7c478bd9Sstevel@tonic-gate jobstopped(proc_t *p) 782*7c478bd9Sstevel@tonic-gate { 783*7c478bd9Sstevel@tonic-gate kthread_t *t; 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) == NULL) 788*7c478bd9Sstevel@tonic-gate return (0); 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate do { 791*7c478bd9Sstevel@tonic-gate thread_lock(t); 792*7c478bd9Sstevel@tonic-gate /* ignore current, zombie and suspended lwps in the test */ 793*7c478bd9Sstevel@tonic-gate if (!(t == curthread || t->t_state == TS_ZOMB || 794*7c478bd9Sstevel@tonic-gate SUSPENDED(t)) && 795*7c478bd9Sstevel@tonic-gate (t->t_state != TS_STOPPED || 796*7c478bd9Sstevel@tonic-gate t->t_whystop != PR_JOBCONTROL)) { 797*7c478bd9Sstevel@tonic-gate thread_unlock(t); 798*7c478bd9Sstevel@tonic-gate return (0); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate thread_unlock(t); 801*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate return (1); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate /* 807*7c478bd9Sstevel@tonic-gate * Put ourself (curthread) into the stopped state and notify tracers. 808*7c478bd9Sstevel@tonic-gate */ 809*7c478bd9Sstevel@tonic-gate void 810*7c478bd9Sstevel@tonic-gate stop(int why, int what) 811*7c478bd9Sstevel@tonic-gate { 812*7c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 813*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 814*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 815*7c478bd9Sstevel@tonic-gate kthread_t *tx; 816*7c478bd9Sstevel@tonic-gate lwpent_t *lep; 817*7c478bd9Sstevel@tonic-gate int procstop; 818*7c478bd9Sstevel@tonic-gate int flags = TS_ALLSTART; 819*7c478bd9Sstevel@tonic-gate hrtime_t stoptime; 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Can't stop a system process. 823*7c478bd9Sstevel@tonic-gate */ 824*7c478bd9Sstevel@tonic-gate if (p == NULL || lwp == NULL || (p->p_flag & SSYS) || p->p_as == &kas) 825*7c478bd9Sstevel@tonic-gate return; 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate if (why != PR_SUSPENDED && why != PR_CHECKPOINT) { 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * Don't stop an lwp with SIGKILL pending. 832*7c478bd9Sstevel@tonic-gate * Don't stop if the process or lwp is exiting. 833*7c478bd9Sstevel@tonic-gate */ 834*7c478bd9Sstevel@tonic-gate if (lwp->lwp_cursig == SIGKILL || 835*7c478bd9Sstevel@tonic-gate sigismember(&t->t_sig, SIGKILL) || 836*7c478bd9Sstevel@tonic-gate sigismember(&p->p_sig, SIGKILL) || 837*7c478bd9Sstevel@tonic-gate (t->t_proc_flag & TP_LWPEXIT) || 838*7c478bd9Sstevel@tonic-gate (p->p_flag & (SEXITLWPS|SKILLED))) { 839*7c478bd9Sstevel@tonic-gate p->p_stopsig = 0; 840*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~(TP_PRSTOP|TP_PRVSTOP); 841*7c478bd9Sstevel@tonic-gate return; 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /* 846*7c478bd9Sstevel@tonic-gate * Make sure we don't deadlock on a recursive call to prstop(). 847*7c478bd9Sstevel@tonic-gate * prstop() sets the lwp_nostop flag. 848*7c478bd9Sstevel@tonic-gate */ 849*7c478bd9Sstevel@tonic-gate if (lwp->lwp_nostop) 850*7c478bd9Sstevel@tonic-gate return; 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * Make sure the lwp is in an orderly state for inspection 854*7c478bd9Sstevel@tonic-gate * by a debugger through /proc or for dumping via core(). 855*7c478bd9Sstevel@tonic-gate */ 856*7c478bd9Sstevel@tonic-gate schedctl_finish_sigblock(t); 857*7c478bd9Sstevel@tonic-gate t->t_proc_flag |= TP_STOPPING; /* must set before dropping p_lock */ 858*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 859*7c478bd9Sstevel@tonic-gate stoptime = gethrtime(); 860*7c478bd9Sstevel@tonic-gate prstop(why, what); 861*7c478bd9Sstevel@tonic-gate (void) undo_watch_step(NULL); 862*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 863*7c478bd9Sstevel@tonic-gate ASSERT(t->t_state == TS_ONPROC); 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate switch (why) { 866*7c478bd9Sstevel@tonic-gate case PR_CHECKPOINT: 867*7c478bd9Sstevel@tonic-gate /* 868*7c478bd9Sstevel@tonic-gate * The situation may have changed since we dropped 869*7c478bd9Sstevel@tonic-gate * and reacquired p->p_lock. Double-check now 870*7c478bd9Sstevel@tonic-gate * whether we should stop or not. 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate if (!(t->t_proc_flag & TP_CHKPT)) { 873*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~TP_STOPPING; 874*7c478bd9Sstevel@tonic-gate return; 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~TP_CHKPT; 877*7c478bd9Sstevel@tonic-gate flags &= ~TS_RESUME; 878*7c478bd9Sstevel@tonic-gate break; 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate case PR_JOBCONTROL: 881*7c478bd9Sstevel@tonic-gate ASSERT(what == SIGSTOP || what == SIGTSTP || 882*7c478bd9Sstevel@tonic-gate what == SIGTTIN || what == SIGTTOU); 883*7c478bd9Sstevel@tonic-gate flags &= ~TS_XSTART; 884*7c478bd9Sstevel@tonic-gate break; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate case PR_SUSPENDED: 887*7c478bd9Sstevel@tonic-gate ASSERT(what == SUSPEND_NORMAL || what == SUSPEND_PAUSE); 888*7c478bd9Sstevel@tonic-gate /* 889*7c478bd9Sstevel@tonic-gate * The situation may have changed since we dropped 890*7c478bd9Sstevel@tonic-gate * and reacquired p->p_lock. Double-check now 891*7c478bd9Sstevel@tonic-gate * whether we should stop or not. 892*7c478bd9Sstevel@tonic-gate */ 893*7c478bd9Sstevel@tonic-gate if (what == SUSPEND_PAUSE) { 894*7c478bd9Sstevel@tonic-gate if (!(t->t_proc_flag & TP_PAUSE)) { 895*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~TP_STOPPING; 896*7c478bd9Sstevel@tonic-gate return; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate flags &= ~TS_UNPAUSE; 899*7c478bd9Sstevel@tonic-gate } else { 900*7c478bd9Sstevel@tonic-gate if (!((t->t_proc_flag & TP_HOLDLWP) || 901*7c478bd9Sstevel@tonic-gate (p->p_flag & (SHOLDFORK|SHOLDFORK1|SHOLDWATCH)))) { 902*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~TP_STOPPING; 903*7c478bd9Sstevel@tonic-gate return; 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * If SHOLDFORK is in effect and we are stopping 907*7c478bd9Sstevel@tonic-gate * while asleep (not at the top of the stack), 908*7c478bd9Sstevel@tonic-gate * we return now to allow the hold to take effect 909*7c478bd9Sstevel@tonic-gate * when we reach the top of the kernel stack. 910*7c478bd9Sstevel@tonic-gate */ 911*7c478bd9Sstevel@tonic-gate if (lwp->lwp_asleep && (p->p_flag & SHOLDFORK)) { 912*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~TP_STOPPING; 913*7c478bd9Sstevel@tonic-gate return; 914*7c478bd9Sstevel@tonic-gate } 915*7c478bd9Sstevel@tonic-gate flags &= ~TS_CSTART; 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate break; 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate default: /* /proc stop */ 920*7c478bd9Sstevel@tonic-gate flags &= ~TS_PSTART; 921*7c478bd9Sstevel@tonic-gate /* 922*7c478bd9Sstevel@tonic-gate * Do synchronous stop unless the async-stop flag is set. 923*7c478bd9Sstevel@tonic-gate * If why is PR_REQUESTED and t->t_dtrace_stop flag is set, 924*7c478bd9Sstevel@tonic-gate * then no debugger is present and we also do synchronous stop. 925*7c478bd9Sstevel@tonic-gate */ 926*7c478bd9Sstevel@tonic-gate if ((why != PR_REQUESTED || t->t_dtrace_stop) && 927*7c478bd9Sstevel@tonic-gate !(p->p_proc_flag & P_PR_ASYNC)) { 928*7c478bd9Sstevel@tonic-gate int notify; 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate for (tx = t->t_forw; tx != t; tx = tx->t_forw) { 931*7c478bd9Sstevel@tonic-gate notify = 0; 932*7c478bd9Sstevel@tonic-gate thread_lock(tx); 933*7c478bd9Sstevel@tonic-gate if (ISTOPPED(tx) || 934*7c478bd9Sstevel@tonic-gate (tx->t_proc_flag & TP_PRSTOP)) { 935*7c478bd9Sstevel@tonic-gate thread_unlock(tx); 936*7c478bd9Sstevel@tonic-gate continue; 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate tx->t_proc_flag |= TP_PRSTOP; 939*7c478bd9Sstevel@tonic-gate tx->t_sig_check = 1; 940*7c478bd9Sstevel@tonic-gate if (tx->t_state == TS_SLEEP && 941*7c478bd9Sstevel@tonic-gate (tx->t_flag & T_WAKEABLE)) { 942*7c478bd9Sstevel@tonic-gate /* 943*7c478bd9Sstevel@tonic-gate * Don't actually wake it up if it's 944*7c478bd9Sstevel@tonic-gate * in one of the lwp_*() syscalls. 945*7c478bd9Sstevel@tonic-gate * Mark it virtually stopped and 946*7c478bd9Sstevel@tonic-gate * notify /proc waiters (below). 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate if (tx->t_wchan0 == NULL) 949*7c478bd9Sstevel@tonic-gate setrun_locked(tx); 950*7c478bd9Sstevel@tonic-gate else { 951*7c478bd9Sstevel@tonic-gate tx->t_proc_flag |= TP_PRVSTOP; 952*7c478bd9Sstevel@tonic-gate tx->t_stoptime = stoptime; 953*7c478bd9Sstevel@tonic-gate notify = 1; 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate /* 957*7c478bd9Sstevel@tonic-gate * force the thread into the kernel 958*7c478bd9Sstevel@tonic-gate * if it is not already there. 959*7c478bd9Sstevel@tonic-gate */ 960*7c478bd9Sstevel@tonic-gate if (tx->t_state == TS_ONPROC && 961*7c478bd9Sstevel@tonic-gate tx->t_cpu != CPU) 962*7c478bd9Sstevel@tonic-gate poke_cpu(tx->t_cpu->cpu_id); 963*7c478bd9Sstevel@tonic-gate thread_unlock(tx); 964*7c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[tx->t_dslot].ld_entry; 965*7c478bd9Sstevel@tonic-gate if (notify && lep->le_trace) 966*7c478bd9Sstevel@tonic-gate prnotify(lep->le_trace); 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate /* 969*7c478bd9Sstevel@tonic-gate * We do this just in case one of the threads we asked 970*7c478bd9Sstevel@tonic-gate * to stop is in holdlwps() (called from cfork()) or 971*7c478bd9Sstevel@tonic-gate * lwp_suspend(). 972*7c478bd9Sstevel@tonic-gate */ 973*7c478bd9Sstevel@tonic-gate cv_broadcast(&p->p_holdlwps); 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate break; 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate t->t_stoptime = stoptime; 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate if (why == PR_JOBCONTROL || (why == PR_SUSPENDED && p->p_stopsig)) { 981*7c478bd9Sstevel@tonic-gate /* 982*7c478bd9Sstevel@tonic-gate * Determine if the whole process is jobstopped. 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate if (jobstopped(p)) { 985*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 986*7c478bd9Sstevel@tonic-gate int sig; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate if ((sig = p->p_stopsig) == 0) 989*7c478bd9Sstevel@tonic-gate p->p_stopsig = (uchar_t)(sig = what); 990*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 991*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); 992*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 993*7c478bd9Sstevel@tonic-gate /* 994*7c478bd9Sstevel@tonic-gate * The last lwp to stop notifies the parent. 995*7c478bd9Sstevel@tonic-gate * Turn off the CLDCONT flag now so the first 996*7c478bd9Sstevel@tonic-gate * lwp to continue knows what to do. 997*7c478bd9Sstevel@tonic-gate */ 998*7c478bd9Sstevel@tonic-gate p->p_pidflag &= ~CLDCONT; 999*7c478bd9Sstevel@tonic-gate p->p_wcode = CLD_STOPPED; 1000*7c478bd9Sstevel@tonic-gate p->p_wdata = sig; 1001*7c478bd9Sstevel@tonic-gate sigcld(p, sqp); 1002*7c478bd9Sstevel@tonic-gate /* 1003*7c478bd9Sstevel@tonic-gate * Grab p->p_lock before releasing pidlock so the 1004*7c478bd9Sstevel@tonic-gate * parent and the child don't have a race condition. 1005*7c478bd9Sstevel@tonic-gate */ 1006*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1007*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1008*7c478bd9Sstevel@tonic-gate p->p_stopsig = 0; 1009*7c478bd9Sstevel@tonic-gate } else if (why == PR_JOBCONTROL && p->p_stopsig == 0) { 1010*7c478bd9Sstevel@tonic-gate /* 1011*7c478bd9Sstevel@tonic-gate * Set p->p_stopsig and wake up sleeping lwps 1012*7c478bd9Sstevel@tonic-gate * so they will stop in sympathy with this lwp. 1013*7c478bd9Sstevel@tonic-gate */ 1014*7c478bd9Sstevel@tonic-gate p->p_stopsig = (uchar_t)what; 1015*7c478bd9Sstevel@tonic-gate pokelwps(p); 1016*7c478bd9Sstevel@tonic-gate /* 1017*7c478bd9Sstevel@tonic-gate * We do this just in case one of the threads we asked 1018*7c478bd9Sstevel@tonic-gate * to stop is in holdlwps() (called from cfork()) or 1019*7c478bd9Sstevel@tonic-gate * lwp_suspend(). 1020*7c478bd9Sstevel@tonic-gate */ 1021*7c478bd9Sstevel@tonic-gate cv_broadcast(&p->p_holdlwps); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate if (why != PR_JOBCONTROL && why != PR_CHECKPOINT) { 1026*7c478bd9Sstevel@tonic-gate /* 1027*7c478bd9Sstevel@tonic-gate * Do process-level notification when all lwps are 1028*7c478bd9Sstevel@tonic-gate * either stopped on events of interest to /proc 1029*7c478bd9Sstevel@tonic-gate * or are stopped showing PR_SUSPENDED or are zombies. 1030*7c478bd9Sstevel@tonic-gate */ 1031*7c478bd9Sstevel@tonic-gate procstop = 1; 1032*7c478bd9Sstevel@tonic-gate for (tx = t->t_forw; procstop && tx != t; tx = tx->t_forw) { 1033*7c478bd9Sstevel@tonic-gate if (VSTOPPED(tx)) 1034*7c478bd9Sstevel@tonic-gate continue; 1035*7c478bd9Sstevel@tonic-gate thread_lock(tx); 1036*7c478bd9Sstevel@tonic-gate switch (tx->t_state) { 1037*7c478bd9Sstevel@tonic-gate case TS_ZOMB: 1038*7c478bd9Sstevel@tonic-gate break; 1039*7c478bd9Sstevel@tonic-gate case TS_STOPPED: 1040*7c478bd9Sstevel@tonic-gate /* neither ISTOPPED nor SUSPENDED? */ 1041*7c478bd9Sstevel@tonic-gate if ((tx->t_schedflag & 1042*7c478bd9Sstevel@tonic-gate (TS_CSTART | TS_UNPAUSE | TS_PSTART)) == 1043*7c478bd9Sstevel@tonic-gate (TS_CSTART | TS_UNPAUSE | TS_PSTART)) 1044*7c478bd9Sstevel@tonic-gate procstop = 0; 1045*7c478bd9Sstevel@tonic-gate break; 1046*7c478bd9Sstevel@tonic-gate case TS_SLEEP: 1047*7c478bd9Sstevel@tonic-gate /* not paused for watchpoints? */ 1048*7c478bd9Sstevel@tonic-gate if (!(tx->t_flag & T_WAKEABLE) || 1049*7c478bd9Sstevel@tonic-gate tx->t_wchan0 == NULL || 1050*7c478bd9Sstevel@tonic-gate !(tx->t_proc_flag & TP_PAUSE)) 1051*7c478bd9Sstevel@tonic-gate procstop = 0; 1052*7c478bd9Sstevel@tonic-gate break; 1053*7c478bd9Sstevel@tonic-gate default: 1054*7c478bd9Sstevel@tonic-gate procstop = 0; 1055*7c478bd9Sstevel@tonic-gate break; 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate thread_unlock(tx); 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate if (procstop) { 1060*7c478bd9Sstevel@tonic-gate /* there must not be any remapped watched pages now */ 1061*7c478bd9Sstevel@tonic-gate ASSERT(p->p_mapcnt == 0); 1062*7c478bd9Sstevel@tonic-gate if (p->p_proc_flag & P_PR_PTRACE) { 1063*7c478bd9Sstevel@tonic-gate /* ptrace() compatibility */ 1064*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1065*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 1066*7c478bd9Sstevel@tonic-gate p->p_wcode = CLD_TRAPPED; 1067*7c478bd9Sstevel@tonic-gate p->p_wdata = (why == PR_SIGNALLED)? 1068*7c478bd9Sstevel@tonic-gate what : SIGTRAP; 1069*7c478bd9Sstevel@tonic-gate cv_broadcast(&p->p_parent->p_cv); 1070*7c478bd9Sstevel@tonic-gate /* 1071*7c478bd9Sstevel@tonic-gate * Grab p->p_lock before releasing pidlock so 1072*7c478bd9Sstevel@tonic-gate * parent and child don't have a race condition. 1073*7c478bd9Sstevel@tonic-gate */ 1074*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1075*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate if (p->p_trace) /* /proc */ 1078*7c478bd9Sstevel@tonic-gate prnotify(p->p_trace); 1079*7c478bd9Sstevel@tonic-gate cv_broadcast(&pr_pid_cv[p->p_slot]); /* pauselwps() */ 1080*7c478bd9Sstevel@tonic-gate cv_broadcast(&p->p_holdlwps); /* holdwatch() */ 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate if (why != PR_SUSPENDED) { 1083*7c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[t->t_dslot].ld_entry; 1084*7c478bd9Sstevel@tonic-gate if (lep->le_trace) /* /proc */ 1085*7c478bd9Sstevel@tonic-gate prnotify(lep->le_trace); 1086*7c478bd9Sstevel@tonic-gate /* 1087*7c478bd9Sstevel@tonic-gate * Special notification for creation of the agent lwp. 1088*7c478bd9Sstevel@tonic-gate */ 1089*7c478bd9Sstevel@tonic-gate if (t == p->p_agenttp && 1090*7c478bd9Sstevel@tonic-gate (t->t_proc_flag & TP_PRSTOP) && 1091*7c478bd9Sstevel@tonic-gate p->p_trace) 1092*7c478bd9Sstevel@tonic-gate prnotify(p->p_trace); 1093*7c478bd9Sstevel@tonic-gate /* 1094*7c478bd9Sstevel@tonic-gate * The situation may have changed since we dropped 1095*7c478bd9Sstevel@tonic-gate * and reacquired p->p_lock. Double-check now 1096*7c478bd9Sstevel@tonic-gate * whether we should stop or not. 1097*7c478bd9Sstevel@tonic-gate */ 1098*7c478bd9Sstevel@tonic-gate if (!(t->t_proc_flag & TP_STOPPING)) { 1099*7c478bd9Sstevel@tonic-gate if (t->t_proc_flag & TP_PRSTOP) 1100*7c478bd9Sstevel@tonic-gate t->t_proc_flag |= TP_STOPPING; 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~(TP_PRSTOP|TP_PRVSTOP); 1103*7c478bd9Sstevel@tonic-gate prnostep(lwp); 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate } 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate if (why == PR_SUSPENDED) { 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate /* 1110*7c478bd9Sstevel@tonic-gate * We always broadcast in the case of SUSPEND_PAUSE. This is 1111*7c478bd9Sstevel@tonic-gate * because checks for TP_PAUSE take precedence over checks for 1112*7c478bd9Sstevel@tonic-gate * SHOLDWATCH. If a thread is trying to stop because of 1113*7c478bd9Sstevel@tonic-gate * SUSPEND_PAUSE and tries to do a holdwatch(), it will be 1114*7c478bd9Sstevel@tonic-gate * waiting for the rest of the threads to enter a stopped state. 1115*7c478bd9Sstevel@tonic-gate * If we are stopping for a SUSPEND_PAUSE, we may be the last 1116*7c478bd9Sstevel@tonic-gate * lwp and not know it, so broadcast just in case. 1117*7c478bd9Sstevel@tonic-gate */ 1118*7c478bd9Sstevel@tonic-gate if (what == SUSPEND_PAUSE || 1119*7c478bd9Sstevel@tonic-gate --p->p_lwprcnt == 0 || (t->t_proc_flag & TP_HOLDLWP)) 1120*7c478bd9Sstevel@tonic-gate cv_broadcast(&p->p_holdlwps); 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate } 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate /* 1125*7c478bd9Sstevel@tonic-gate * Need to do this here (rather than after the thread is officially 1126*7c478bd9Sstevel@tonic-gate * stopped) because we can't call mutex_enter from a stopped thread. 1127*7c478bd9Sstevel@tonic-gate */ 1128*7c478bd9Sstevel@tonic-gate if (why == PR_CHECKPOINT) 1129*7c478bd9Sstevel@tonic-gate del_one_utstop(); 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate thread_lock(t); 1132*7c478bd9Sstevel@tonic-gate ASSERT((t->t_schedflag & TS_ALLSTART) == 0); 1133*7c478bd9Sstevel@tonic-gate t->t_schedflag |= flags; 1134*7c478bd9Sstevel@tonic-gate t->t_whystop = (short)why; 1135*7c478bd9Sstevel@tonic-gate t->t_whatstop = (short)what; 1136*7c478bd9Sstevel@tonic-gate CL_STOP(t, why, what); 1137*7c478bd9Sstevel@tonic-gate (void) new_mstate(t, LMS_STOPPED); 1138*7c478bd9Sstevel@tonic-gate thread_stop(t); /* set stop state and drop lock */ 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate if (why != PR_SUSPENDED && why != PR_CHECKPOINT) { 1141*7c478bd9Sstevel@tonic-gate /* 1142*7c478bd9Sstevel@tonic-gate * We may have gotten a SIGKILL or a SIGCONT when 1143*7c478bd9Sstevel@tonic-gate * we released p->p_lock; make one last check. 1144*7c478bd9Sstevel@tonic-gate * Also check for a /proc run-on-last-close. 1145*7c478bd9Sstevel@tonic-gate */ 1146*7c478bd9Sstevel@tonic-gate if (sigismember(&t->t_sig, SIGKILL) || 1147*7c478bd9Sstevel@tonic-gate sigismember(&p->p_sig, SIGKILL) || 1148*7c478bd9Sstevel@tonic-gate (t->t_proc_flag & TP_LWPEXIT) || 1149*7c478bd9Sstevel@tonic-gate (p->p_flag & (SEXITLWPS|SKILLED))) { 1150*7c478bd9Sstevel@tonic-gate p->p_stopsig = 0; 1151*7c478bd9Sstevel@tonic-gate thread_lock(t); 1152*7c478bd9Sstevel@tonic-gate t->t_schedflag |= TS_XSTART | TS_PSTART; 1153*7c478bd9Sstevel@tonic-gate setrun_locked(t); 1154*7c478bd9Sstevel@tonic-gate thread_unlock_nopreempt(t); 1155*7c478bd9Sstevel@tonic-gate } else if (why == PR_JOBCONTROL) { 1156*7c478bd9Sstevel@tonic-gate if (p->p_flag & SSCONT) { 1157*7c478bd9Sstevel@tonic-gate /* 1158*7c478bd9Sstevel@tonic-gate * This resulted from a SIGCONT posted 1159*7c478bd9Sstevel@tonic-gate * while we were not holding p->p_lock. 1160*7c478bd9Sstevel@tonic-gate */ 1161*7c478bd9Sstevel@tonic-gate p->p_stopsig = 0; 1162*7c478bd9Sstevel@tonic-gate thread_lock(t); 1163*7c478bd9Sstevel@tonic-gate t->t_schedflag |= TS_XSTART; 1164*7c478bd9Sstevel@tonic-gate setrun_locked(t); 1165*7c478bd9Sstevel@tonic-gate thread_unlock_nopreempt(t); 1166*7c478bd9Sstevel@tonic-gate } 1167*7c478bd9Sstevel@tonic-gate } else if (!(t->t_proc_flag & TP_STOPPING)) { 1168*7c478bd9Sstevel@tonic-gate /* 1169*7c478bd9Sstevel@tonic-gate * This resulted from a /proc run-on-last-close. 1170*7c478bd9Sstevel@tonic-gate */ 1171*7c478bd9Sstevel@tonic-gate thread_lock(t); 1172*7c478bd9Sstevel@tonic-gate t->t_schedflag |= TS_PSTART; 1173*7c478bd9Sstevel@tonic-gate setrun_locked(t); 1174*7c478bd9Sstevel@tonic-gate thread_unlock_nopreempt(t); 1175*7c478bd9Sstevel@tonic-gate } 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate t->t_proc_flag &= ~TP_STOPPING; 1179*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate swtch(); 1182*7c478bd9Sstevel@tonic-gate setallwatch(); /* reestablish any watchpoints set while stopped */ 1183*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1184*7c478bd9Sstevel@tonic-gate prbarrier(p); /* barrier against /proc locking */ 1185*7c478bd9Sstevel@tonic-gate } 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate /* Interface for resetting user thread stop count. */ 1188*7c478bd9Sstevel@tonic-gate void 1189*7c478bd9Sstevel@tonic-gate utstop_init(void) 1190*7c478bd9Sstevel@tonic-gate { 1191*7c478bd9Sstevel@tonic-gate mutex_enter(&thread_stop_lock); 1192*7c478bd9Sstevel@tonic-gate num_utstop = 0; 1193*7c478bd9Sstevel@tonic-gate mutex_exit(&thread_stop_lock); 1194*7c478bd9Sstevel@tonic-gate } 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate /* Interface for registering a user thread stop request. */ 1197*7c478bd9Sstevel@tonic-gate void 1198*7c478bd9Sstevel@tonic-gate add_one_utstop(void) 1199*7c478bd9Sstevel@tonic-gate { 1200*7c478bd9Sstevel@tonic-gate mutex_enter(&thread_stop_lock); 1201*7c478bd9Sstevel@tonic-gate num_utstop++; 1202*7c478bd9Sstevel@tonic-gate mutex_exit(&thread_stop_lock); 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate /* Interface for cancelling a user thread stop request */ 1206*7c478bd9Sstevel@tonic-gate void 1207*7c478bd9Sstevel@tonic-gate del_one_utstop(void) 1208*7c478bd9Sstevel@tonic-gate { 1209*7c478bd9Sstevel@tonic-gate mutex_enter(&thread_stop_lock); 1210*7c478bd9Sstevel@tonic-gate num_utstop--; 1211*7c478bd9Sstevel@tonic-gate if (num_utstop == 0) 1212*7c478bd9Sstevel@tonic-gate cv_broadcast(&utstop_cv); 1213*7c478bd9Sstevel@tonic-gate mutex_exit(&thread_stop_lock); 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate /* Interface to wait for all user threads to be stopped */ 1217*7c478bd9Sstevel@tonic-gate void 1218*7c478bd9Sstevel@tonic-gate utstop_timedwait(clock_t ticks) 1219*7c478bd9Sstevel@tonic-gate { 1220*7c478bd9Sstevel@tonic-gate mutex_enter(&thread_stop_lock); 1221*7c478bd9Sstevel@tonic-gate if (num_utstop > 0) 1222*7c478bd9Sstevel@tonic-gate (void) cv_timedwait(&utstop_cv, &thread_stop_lock, 1223*7c478bd9Sstevel@tonic-gate ticks + lbolt); 1224*7c478bd9Sstevel@tonic-gate mutex_exit(&thread_stop_lock); 1225*7c478bd9Sstevel@tonic-gate } 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate /* 1228*7c478bd9Sstevel@tonic-gate * Perform the action specified by the current signal. 1229*7c478bd9Sstevel@tonic-gate * The usual sequence is: 1230*7c478bd9Sstevel@tonic-gate * if (issig()) 1231*7c478bd9Sstevel@tonic-gate * psig(); 1232*7c478bd9Sstevel@tonic-gate * The signal bit has already been cleared by issig(), 1233*7c478bd9Sstevel@tonic-gate * the current signal number has been stored in lwp_cursig, 1234*7c478bd9Sstevel@tonic-gate * and the current siginfo is now referenced by lwp_curinfo. 1235*7c478bd9Sstevel@tonic-gate */ 1236*7c478bd9Sstevel@tonic-gate void 1237*7c478bd9Sstevel@tonic-gate psig(void) 1238*7c478bd9Sstevel@tonic-gate { 1239*7c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 1240*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 1241*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 1242*7c478bd9Sstevel@tonic-gate void (*func)(); 1243*7c478bd9Sstevel@tonic-gate int sig, rc, code, ext; 1244*7c478bd9Sstevel@tonic-gate pid_t pid = -1; 1245*7c478bd9Sstevel@tonic-gate id_t ctid = 0; 1246*7c478bd9Sstevel@tonic-gate zoneid_t zoneid = -1; 1247*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp = NULL; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1250*7c478bd9Sstevel@tonic-gate schedctl_finish_sigblock(t); 1251*7c478bd9Sstevel@tonic-gate code = CLD_KILLED; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate if (p->p_flag & SEXITLWPS) { 1254*7c478bd9Sstevel@tonic-gate lwp_exit(); 1255*7c478bd9Sstevel@tonic-gate return; /* not reached */ 1256*7c478bd9Sstevel@tonic-gate } 1257*7c478bd9Sstevel@tonic-gate sig = lwp->lwp_cursig; 1258*7c478bd9Sstevel@tonic-gate ext = lwp->lwp_extsig; 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate ASSERT(sig < NSIG); 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate /* 1263*7c478bd9Sstevel@tonic-gate * Re-check lwp_cursig after we acquire p_lock. Since p_lock was 1264*7c478bd9Sstevel@tonic-gate * dropped between issig() and psig(), a debugger may have cleared 1265*7c478bd9Sstevel@tonic-gate * lwp_cursig via /proc in the intervening window. 1266*7c478bd9Sstevel@tonic-gate */ 1267*7c478bd9Sstevel@tonic-gate if (sig == 0) { 1268*7c478bd9Sstevel@tonic-gate if (lwp->lwp_curinfo) { 1269*7c478bd9Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo); 1270*7c478bd9Sstevel@tonic-gate lwp->lwp_curinfo = NULL; 1271*7c478bd9Sstevel@tonic-gate } 1272*7c478bd9Sstevel@tonic-gate if (t->t_flag & T_TOMASK) { /* sigsuspend or pollsys */ 1273*7c478bd9Sstevel@tonic-gate t->t_flag &= ~T_TOMASK; 1274*7c478bd9Sstevel@tonic-gate t->t_hold = lwp->lwp_sigoldmask; 1275*7c478bd9Sstevel@tonic-gate } 1276*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1277*7c478bd9Sstevel@tonic-gate return; 1278*7c478bd9Sstevel@tonic-gate } 1279*7c478bd9Sstevel@tonic-gate func = u.u_signal[sig-1]; 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate /* 1282*7c478bd9Sstevel@tonic-gate * The signal disposition could have changed since we promoted 1283*7c478bd9Sstevel@tonic-gate * this signal from pending to current (we dropped p->p_lock). 1284*7c478bd9Sstevel@tonic-gate * This can happen only in a multi-threaded process. 1285*7c478bd9Sstevel@tonic-gate */ 1286*7c478bd9Sstevel@tonic-gate if (sigismember(&p->p_ignore, sig) || 1287*7c478bd9Sstevel@tonic-gate (func == SIG_DFL && sigismember(&stopdefault, sig))) { 1288*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = 0; 1289*7c478bd9Sstevel@tonic-gate lwp->lwp_extsig = 0; 1290*7c478bd9Sstevel@tonic-gate if (lwp->lwp_curinfo) { 1291*7c478bd9Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo); 1292*7c478bd9Sstevel@tonic-gate lwp->lwp_curinfo = NULL; 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate if (t->t_flag & T_TOMASK) { /* sigsuspend or pollsys */ 1295*7c478bd9Sstevel@tonic-gate t->t_flag &= ~T_TOMASK; 1296*7c478bd9Sstevel@tonic-gate t->t_hold = lwp->lwp_sigoldmask; 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1299*7c478bd9Sstevel@tonic-gate return; 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate /* 1303*7c478bd9Sstevel@tonic-gate * We check lwp_curinfo first since pr_setsig can actually 1304*7c478bd9Sstevel@tonic-gate * stuff a sigqueue_t there for SIGKILL. 1305*7c478bd9Sstevel@tonic-gate */ 1306*7c478bd9Sstevel@tonic-gate if (lwp->lwp_curinfo) { 1307*7c478bd9Sstevel@tonic-gate sqp = lwp->lwp_curinfo; 1308*7c478bd9Sstevel@tonic-gate } else if (sig == SIGKILL && p->p_killsqp) { 1309*7c478bd9Sstevel@tonic-gate sqp = p->p_killsqp; 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate if (sqp != NULL) { 1313*7c478bd9Sstevel@tonic-gate if (SI_FROMUSER(&sqp->sq_info)) { 1314*7c478bd9Sstevel@tonic-gate pid = sqp->sq_info.si_pid; 1315*7c478bd9Sstevel@tonic-gate ctid = sqp->sq_info.si_ctid; 1316*7c478bd9Sstevel@tonic-gate zoneid = sqp->sq_info.si_zoneid; 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate /* 1319*7c478bd9Sstevel@tonic-gate * If we have a sigqueue_t, its sq_external value 1320*7c478bd9Sstevel@tonic-gate * trumps the lwp_extsig value. It is theoretically 1321*7c478bd9Sstevel@tonic-gate * possible to make lwp_extsig reflect reality, but it 1322*7c478bd9Sstevel@tonic-gate * would unnecessarily complicate things elsewhere. 1323*7c478bd9Sstevel@tonic-gate */ 1324*7c478bd9Sstevel@tonic-gate ext = sqp->sq_external; 1325*7c478bd9Sstevel@tonic-gate } 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate if (func == SIG_DFL) { 1328*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1329*7c478bd9Sstevel@tonic-gate DTRACE_PROC3(signal__handle, int, sig, k_siginfo_t *, 1330*7c478bd9Sstevel@tonic-gate NULL, void (*)(void), func); 1331*7c478bd9Sstevel@tonic-gate } else { 1332*7c478bd9Sstevel@tonic-gate k_siginfo_t *sip = NULL; 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate /* 1335*7c478bd9Sstevel@tonic-gate * If DTrace user-land tracing is active, give DTrace a 1336*7c478bd9Sstevel@tonic-gate * chance to defer the signal until after tracing is 1337*7c478bd9Sstevel@tonic-gate * complete. 1338*7c478bd9Sstevel@tonic-gate */ 1339*7c478bd9Sstevel@tonic-gate if (t->t_dtrace_on && dtrace_safe_defer_signal()) { 1340*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1341*7c478bd9Sstevel@tonic-gate return; 1342*7c478bd9Sstevel@tonic-gate } 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate /* 1345*7c478bd9Sstevel@tonic-gate * save siginfo pointer here, in case the 1346*7c478bd9Sstevel@tonic-gate * the signal's reset bit is on 1347*7c478bd9Sstevel@tonic-gate * 1348*7c478bd9Sstevel@tonic-gate * The presence of a current signal prevents paging 1349*7c478bd9Sstevel@tonic-gate * from succeeding over a network. We copy the current 1350*7c478bd9Sstevel@tonic-gate * signal information to the side and cancel the current 1351*7c478bd9Sstevel@tonic-gate * signal so that sendsig() will succeed. 1352*7c478bd9Sstevel@tonic-gate */ 1353*7c478bd9Sstevel@tonic-gate if (sigismember(&p->p_siginfo, sig)) { 1354*7c478bd9Sstevel@tonic-gate if (sqp) { 1355*7c478bd9Sstevel@tonic-gate bcopy(&sqp->sq_info, &lwp->lwp_siginfo, 1356*7c478bd9Sstevel@tonic-gate sizeof (k_siginfo_t)); 1357*7c478bd9Sstevel@tonic-gate sip = &lwp->lwp_siginfo; 1358*7c478bd9Sstevel@tonic-gate } else if (sig == SIGPROF && 1359*7c478bd9Sstevel@tonic-gate t->t_rprof != NULL && 1360*7c478bd9Sstevel@tonic-gate t->t_rprof->rp_anystate && 1361*7c478bd9Sstevel@tonic-gate lwp->lwp_siginfo.si_signo == SIGPROF) { 1362*7c478bd9Sstevel@tonic-gate sip = &lwp->lwp_siginfo; 1363*7c478bd9Sstevel@tonic-gate } 1364*7c478bd9Sstevel@tonic-gate } 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate if (t->t_flag & T_TOMASK) 1367*7c478bd9Sstevel@tonic-gate t->t_flag &= ~T_TOMASK; 1368*7c478bd9Sstevel@tonic-gate else 1369*7c478bd9Sstevel@tonic-gate lwp->lwp_sigoldmask = t->t_hold; 1370*7c478bd9Sstevel@tonic-gate sigorset(&t->t_hold, &u.u_sigmask[sig-1]); 1371*7c478bd9Sstevel@tonic-gate if (!sigismember(&u.u_signodefer, sig)) 1372*7c478bd9Sstevel@tonic-gate sigaddset(&t->t_hold, sig); 1373*7c478bd9Sstevel@tonic-gate if (sigismember(&u.u_sigresethand, sig)) 1374*7c478bd9Sstevel@tonic-gate setsigact(sig, SIG_DFL, nullsmask, 0); 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate DTRACE_PROC3(signal__handle, int, sig, k_siginfo_t *, 1377*7c478bd9Sstevel@tonic-gate sip, void (*)(void), func); 1378*7c478bd9Sstevel@tonic-gate 1379*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = 0; 1380*7c478bd9Sstevel@tonic-gate lwp->lwp_extsig = 0; 1381*7c478bd9Sstevel@tonic-gate if (lwp->lwp_curinfo) { 1382*7c478bd9Sstevel@tonic-gate /* p->p_killsqp is freed by freeproc */ 1383*7c478bd9Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo); 1384*7c478bd9Sstevel@tonic-gate lwp->lwp_curinfo = NULL; 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1387*7c478bd9Sstevel@tonic-gate lwp->lwp_ru.nsignals++; 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_NATIVE) 1390*7c478bd9Sstevel@tonic-gate rc = sendsig(sig, sip, func); 1391*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1392*7c478bd9Sstevel@tonic-gate else 1393*7c478bd9Sstevel@tonic-gate rc = sendsig32(sig, sip, func); 1394*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1395*7c478bd9Sstevel@tonic-gate if (rc) 1396*7c478bd9Sstevel@tonic-gate return; 1397*7c478bd9Sstevel@tonic-gate sig = lwp->lwp_cursig = SIGSEGV; 1398*7c478bd9Sstevel@tonic-gate ext = 0; /* lwp_extsig was set above */ 1399*7c478bd9Sstevel@tonic-gate pid = -1; 1400*7c478bd9Sstevel@tonic-gate ctid = 0; 1401*7c478bd9Sstevel@tonic-gate } 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate if (sigismember(&coredefault, sig)) { 1404*7c478bd9Sstevel@tonic-gate /* 1405*7c478bd9Sstevel@tonic-gate * Terminate all LWPs but don't discard them. 1406*7c478bd9Sstevel@tonic-gate * If another lwp beat us to the punch by calling exit(), 1407*7c478bd9Sstevel@tonic-gate * evaporate now. 1408*7c478bd9Sstevel@tonic-gate */ 1409*7c478bd9Sstevel@tonic-gate if (exitlwps(1) != 0) { 1410*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1411*7c478bd9Sstevel@tonic-gate lwp_exit(); 1412*7c478bd9Sstevel@tonic-gate } 1413*7c478bd9Sstevel@tonic-gate /* if we got a SIGKILL from anywhere, no core dump */ 1414*7c478bd9Sstevel@tonic-gate if (p->p_flag & SKILLED) { 1415*7c478bd9Sstevel@tonic-gate sig = SIGKILL; 1416*7c478bd9Sstevel@tonic-gate ext = (p->p_flag & SEXTKILLED) != 0; 1417*7c478bd9Sstevel@tonic-gate } else { 1418*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 1419*7c478bd9Sstevel@tonic-gate if (audit_active) /* audit core dump */ 1420*7c478bd9Sstevel@tonic-gate audit_core_start(sig); 1421*7c478bd9Sstevel@tonic-gate #endif 1422*7c478bd9Sstevel@tonic-gate if (core(sig, ext) == 0) 1423*7c478bd9Sstevel@tonic-gate code = CLD_DUMPED; 1424*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 1425*7c478bd9Sstevel@tonic-gate if (audit_active) /* audit core dump */ 1426*7c478bd9Sstevel@tonic-gate audit_core_finish(code); 1427*7c478bd9Sstevel@tonic-gate #endif 1428*7c478bd9Sstevel@tonic-gate } 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate if (ext) 1431*7c478bd9Sstevel@tonic-gate contract_process_sig(p->p_ct_process, p, sig, pid, ctid, 1432*7c478bd9Sstevel@tonic-gate zoneid); 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate exit(code, sig); 1435*7c478bd9Sstevel@tonic-gate } 1436*7c478bd9Sstevel@tonic-gate 1437*7c478bd9Sstevel@tonic-gate /* 1438*7c478bd9Sstevel@tonic-gate * Find next unheld signal in ssp for thread t. 1439*7c478bd9Sstevel@tonic-gate */ 1440*7c478bd9Sstevel@tonic-gate int 1441*7c478bd9Sstevel@tonic-gate fsig(k_sigset_t *ssp, kthread_t *t) 1442*7c478bd9Sstevel@tonic-gate { 1443*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 1444*7c478bd9Sstevel@tonic-gate user_t *up = PTOU(p); 1445*7c478bd9Sstevel@tonic-gate int i; 1446*7c478bd9Sstevel@tonic-gate k_sigset_t temp; 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate /* 1451*7c478bd9Sstevel@tonic-gate * Don't promote any signals for the parent of a vfork()d 1452*7c478bd9Sstevel@tonic-gate * child that hasn't yet released the parent's memory. 1453*7c478bd9Sstevel@tonic-gate */ 1454*7c478bd9Sstevel@tonic-gate if (p->p_flag & SVFWAIT) 1455*7c478bd9Sstevel@tonic-gate return (0); 1456*7c478bd9Sstevel@tonic-gate 1457*7c478bd9Sstevel@tonic-gate temp = *ssp; 1458*7c478bd9Sstevel@tonic-gate sigdiffset(&temp, &t->t_hold); 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate /* 1461*7c478bd9Sstevel@tonic-gate * Don't promote stopping signals (except SIGSTOP) for a child 1462*7c478bd9Sstevel@tonic-gate * of vfork() that hasn't yet released the parent's memory. 1463*7c478bd9Sstevel@tonic-gate */ 1464*7c478bd9Sstevel@tonic-gate if (p->p_flag & SVFORK) 1465*7c478bd9Sstevel@tonic-gate sigdiffset(&temp, &holdvfork); 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate /* 1468*7c478bd9Sstevel@tonic-gate * Don't promote a signal that will stop 1469*7c478bd9Sstevel@tonic-gate * the process when lwp_nostop is set. 1470*7c478bd9Sstevel@tonic-gate */ 1471*7c478bd9Sstevel@tonic-gate if (ttolwp(t)->lwp_nostop) { 1472*7c478bd9Sstevel@tonic-gate sigdelset(&temp, SIGSTOP); 1473*7c478bd9Sstevel@tonic-gate if (!p->p_pgidp->pid_pgorphaned) { 1474*7c478bd9Sstevel@tonic-gate if (up->u_signal[SIGTSTP-1] == SIG_DFL) 1475*7c478bd9Sstevel@tonic-gate sigdelset(&temp, SIGTSTP); 1476*7c478bd9Sstevel@tonic-gate if (up->u_signal[SIGTTIN-1] == SIG_DFL) 1477*7c478bd9Sstevel@tonic-gate sigdelset(&temp, SIGTTIN); 1478*7c478bd9Sstevel@tonic-gate if (up->u_signal[SIGTTOU-1] == SIG_DFL) 1479*7c478bd9Sstevel@tonic-gate sigdelset(&temp, SIGTTOU); 1480*7c478bd9Sstevel@tonic-gate } 1481*7c478bd9Sstevel@tonic-gate } 1482*7c478bd9Sstevel@tonic-gate 1483*7c478bd9Sstevel@tonic-gate /* 1484*7c478bd9Sstevel@tonic-gate * Choose SIGKILL and SIGPROF before all other pending signals. 1485*7c478bd9Sstevel@tonic-gate * The rest are promoted in signal number order. 1486*7c478bd9Sstevel@tonic-gate */ 1487*7c478bd9Sstevel@tonic-gate if (sigismember(&temp, SIGKILL)) 1488*7c478bd9Sstevel@tonic-gate return (SIGKILL); 1489*7c478bd9Sstevel@tonic-gate if (sigismember(&temp, SIGPROF)) 1490*7c478bd9Sstevel@tonic-gate return (SIGPROF); 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (temp) / sizeof (temp.__sigbits[0]); i++) { 1493*7c478bd9Sstevel@tonic-gate if (temp.__sigbits[i]) 1494*7c478bd9Sstevel@tonic-gate return ((i * NBBY * sizeof (temp.__sigbits[0])) + 1495*7c478bd9Sstevel@tonic-gate lowbit(temp.__sigbits[i])); 1496*7c478bd9Sstevel@tonic-gate } 1497*7c478bd9Sstevel@tonic-gate 1498*7c478bd9Sstevel@tonic-gate return (0); 1499*7c478bd9Sstevel@tonic-gate } 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate void 1502*7c478bd9Sstevel@tonic-gate setsigact(int sig, void (*disp)(), k_sigset_t mask, int flags) 1503*7c478bd9Sstevel@tonic-gate { 1504*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 1505*7c478bd9Sstevel@tonic-gate kthread_t *t; 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate u.u_signal[sig - 1] = disp; 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate /* 1512*7c478bd9Sstevel@tonic-gate * Honor the SA_SIGINFO flag if the signal is being caught. 1513*7c478bd9Sstevel@tonic-gate * Force the SA_SIGINFO flag if the signal is not being caught. 1514*7c478bd9Sstevel@tonic-gate * This is necessary to make sigqueue() and sigwaitinfo() work 1515*7c478bd9Sstevel@tonic-gate * properly together when the signal is set to default or is 1516*7c478bd9Sstevel@tonic-gate * being temporarily ignored. 1517*7c478bd9Sstevel@tonic-gate */ 1518*7c478bd9Sstevel@tonic-gate if ((flags & SA_SIGINFO) || disp == SIG_DFL || disp == SIG_IGN) 1519*7c478bd9Sstevel@tonic-gate sigaddset(&p->p_siginfo, sig); 1520*7c478bd9Sstevel@tonic-gate else 1521*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_siginfo, sig); 1522*7c478bd9Sstevel@tonic-gate 1523*7c478bd9Sstevel@tonic-gate if (disp != SIG_DFL && disp != SIG_IGN) { 1524*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_ignore, sig); 1525*7c478bd9Sstevel@tonic-gate u.u_sigmask[sig - 1] = mask; 1526*7c478bd9Sstevel@tonic-gate if (!sigismember(&cantreset, sig)) { 1527*7c478bd9Sstevel@tonic-gate if (flags & SA_RESETHAND) 1528*7c478bd9Sstevel@tonic-gate sigaddset(&u.u_sigresethand, sig); 1529*7c478bd9Sstevel@tonic-gate else 1530*7c478bd9Sstevel@tonic-gate sigdelset(&u.u_sigresethand, sig); 1531*7c478bd9Sstevel@tonic-gate } 1532*7c478bd9Sstevel@tonic-gate if (flags & SA_NODEFER) 1533*7c478bd9Sstevel@tonic-gate sigaddset(&u.u_signodefer, sig); 1534*7c478bd9Sstevel@tonic-gate else 1535*7c478bd9Sstevel@tonic-gate sigdelset(&u.u_signodefer, sig); 1536*7c478bd9Sstevel@tonic-gate if (flags & SA_RESTART) 1537*7c478bd9Sstevel@tonic-gate sigaddset(&u.u_sigrestart, sig); 1538*7c478bd9Sstevel@tonic-gate else 1539*7c478bd9Sstevel@tonic-gate sigdelset(&u.u_sigrestart, sig); 1540*7c478bd9Sstevel@tonic-gate if (flags & SA_ONSTACK) 1541*7c478bd9Sstevel@tonic-gate sigaddset(&u.u_sigonstack, sig); 1542*7c478bd9Sstevel@tonic-gate else 1543*7c478bd9Sstevel@tonic-gate sigdelset(&u.u_sigonstack, sig); 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate } else if (disp == SIG_IGN || 1546*7c478bd9Sstevel@tonic-gate (disp == SIG_DFL && sigismember(&ignoredefault, sig))) { 1547*7c478bd9Sstevel@tonic-gate /* 1548*7c478bd9Sstevel@tonic-gate * Setting the signal action to SIG_IGN results in the 1549*7c478bd9Sstevel@tonic-gate * discarding of all pending signals of that signal number. 1550*7c478bd9Sstevel@tonic-gate * Setting the signal action to SIG_DFL does the same *only* 1551*7c478bd9Sstevel@tonic-gate * if the signal's default behavior is to be ignored. 1552*7c478bd9Sstevel@tonic-gate */ 1553*7c478bd9Sstevel@tonic-gate sigaddset(&p->p_ignore, sig); 1554*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_sig, sig); 1555*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_extsig, sig); 1556*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, sig); 1557*7c478bd9Sstevel@tonic-gate t = p->p_tlist; 1558*7c478bd9Sstevel@tonic-gate do { 1559*7c478bd9Sstevel@tonic-gate sigdelset(&t->t_sig, sig); 1560*7c478bd9Sstevel@tonic-gate sigdelset(&t->t_extsig, sig); 1561*7c478bd9Sstevel@tonic-gate sigdelq(p, t, sig); 1562*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate } else { 1565*7c478bd9Sstevel@tonic-gate /* 1566*7c478bd9Sstevel@tonic-gate * The signal action is being set to SIG_DFL and the default 1567*7c478bd9Sstevel@tonic-gate * behavior is to do something: make sure it is not ignored. 1568*7c478bd9Sstevel@tonic-gate */ 1569*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_ignore, sig); 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate 1572*7c478bd9Sstevel@tonic-gate if (sig == SIGCLD) { 1573*7c478bd9Sstevel@tonic-gate if (flags & SA_NOCLDWAIT) 1574*7c478bd9Sstevel@tonic-gate p->p_flag |= SNOWAIT; 1575*7c478bd9Sstevel@tonic-gate else 1576*7c478bd9Sstevel@tonic-gate p->p_flag &= ~SNOWAIT; 1577*7c478bd9Sstevel@tonic-gate 1578*7c478bd9Sstevel@tonic-gate if (flags & SA_NOCLDSTOP) 1579*7c478bd9Sstevel@tonic-gate p->p_flag &= ~SJCTL; 1580*7c478bd9Sstevel@tonic-gate else 1581*7c478bd9Sstevel@tonic-gate p->p_flag |= SJCTL; 1582*7c478bd9Sstevel@tonic-gate 1583*7c478bd9Sstevel@tonic-gate if (p->p_flag & SNOWAIT || disp == SIG_IGN) { 1584*7c478bd9Sstevel@tonic-gate proc_t *cp, *tp; 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1587*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 1588*7c478bd9Sstevel@tonic-gate for (cp = p->p_child; cp != NULL; cp = tp) { 1589*7c478bd9Sstevel@tonic-gate tp = cp->p_sibling; 1590*7c478bd9Sstevel@tonic-gate if (cp->p_stat == SZOMB) 1591*7c478bd9Sstevel@tonic-gate freeproc(cp); 1592*7c478bd9Sstevel@tonic-gate } 1593*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1594*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate } 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate /* 1600*7c478bd9Sstevel@tonic-gate * Set all signal actions not already set to SIG_DFL or SIG_IGN to SIG_DFL. 1601*7c478bd9Sstevel@tonic-gate * Called from exec_common() for a process undergoing execve() 1602*7c478bd9Sstevel@tonic-gate * and from cfork() for a newly-created child of vfork(). 1603*7c478bd9Sstevel@tonic-gate * In the vfork() case, 'p' is not the current process. 1604*7c478bd9Sstevel@tonic-gate * In both cases, there is only one thread in the process. 1605*7c478bd9Sstevel@tonic-gate */ 1606*7c478bd9Sstevel@tonic-gate void 1607*7c478bd9Sstevel@tonic-gate sigdefault(proc_t *p) 1608*7c478bd9Sstevel@tonic-gate { 1609*7c478bd9Sstevel@tonic-gate kthread_t *t = p->p_tlist; 1610*7c478bd9Sstevel@tonic-gate struct user *up = PTOU(p); 1611*7c478bd9Sstevel@tonic-gate int sig; 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate for (sig = 1; sig < NSIG; sig++) { 1616*7c478bd9Sstevel@tonic-gate if (up->u_signal[sig - 1] != SIG_DFL && 1617*7c478bd9Sstevel@tonic-gate up->u_signal[sig - 1] != SIG_IGN) { 1618*7c478bd9Sstevel@tonic-gate up->u_signal[sig - 1] = SIG_DFL; 1619*7c478bd9Sstevel@tonic-gate sigemptyset(&up->u_sigmask[sig - 1]); 1620*7c478bd9Sstevel@tonic-gate if (sigismember(&ignoredefault, sig)) { 1621*7c478bd9Sstevel@tonic-gate sigdelq(p, NULL, sig); 1622*7c478bd9Sstevel@tonic-gate sigdelq(p, t, sig); 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate if (sig == SIGCLD) 1625*7c478bd9Sstevel@tonic-gate p->p_flag &= ~(SNOWAIT|SJCTL); 1626*7c478bd9Sstevel@tonic-gate } 1627*7c478bd9Sstevel@tonic-gate } 1628*7c478bd9Sstevel@tonic-gate sigorset(&p->p_ignore, &ignoredefault); 1629*7c478bd9Sstevel@tonic-gate sigfillset(&p->p_siginfo); 1630*7c478bd9Sstevel@tonic-gate sigdiffset(&p->p_siginfo, &cantmask); 1631*7c478bd9Sstevel@tonic-gate sigdiffset(&p->p_sig, &ignoredefault); 1632*7c478bd9Sstevel@tonic-gate sigdiffset(&p->p_extsig, &ignoredefault); 1633*7c478bd9Sstevel@tonic-gate sigdiffset(&t->t_sig, &ignoredefault); 1634*7c478bd9Sstevel@tonic-gate sigdiffset(&t->t_extsig, &ignoredefault); 1635*7c478bd9Sstevel@tonic-gate } 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate void 1638*7c478bd9Sstevel@tonic-gate sigcld(proc_t *cp, sigqueue_t *sqp) 1639*7c478bd9Sstevel@tonic-gate { 1640*7c478bd9Sstevel@tonic-gate proc_t *pp = cp->p_parent; 1641*7c478bd9Sstevel@tonic-gate 1642*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate switch (cp->p_wcode) { 1645*7c478bd9Sstevel@tonic-gate case CLD_EXITED: 1646*7c478bd9Sstevel@tonic-gate case CLD_DUMPED: 1647*7c478bd9Sstevel@tonic-gate case CLD_KILLED: 1648*7c478bd9Sstevel@tonic-gate ASSERT(cp->p_stat == SZOMB); 1649*7c478bd9Sstevel@tonic-gate /* 1650*7c478bd9Sstevel@tonic-gate * The broadcast on p_srwchan_cv is a kludge to 1651*7c478bd9Sstevel@tonic-gate * wakeup a possible thread in uadmin(A_SHUTDOWN). 1652*7c478bd9Sstevel@tonic-gate */ 1653*7c478bd9Sstevel@tonic-gate cv_broadcast(&cp->p_srwchan_cv); 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate /* 1656*7c478bd9Sstevel@tonic-gate * Add to newstate list of the parent 1657*7c478bd9Sstevel@tonic-gate */ 1658*7c478bd9Sstevel@tonic-gate add_ns(pp, cp); 1659*7c478bd9Sstevel@tonic-gate 1660*7c478bd9Sstevel@tonic-gate cv_broadcast(&pp->p_cv); 1661*7c478bd9Sstevel@tonic-gate if ((pp->p_flag & SNOWAIT) || 1662*7c478bd9Sstevel@tonic-gate (PTOU(pp)->u_signal[SIGCLD - 1] == SIG_IGN)) 1663*7c478bd9Sstevel@tonic-gate freeproc(cp); 1664*7c478bd9Sstevel@tonic-gate else { 1665*7c478bd9Sstevel@tonic-gate post_sigcld(cp, sqp); 1666*7c478bd9Sstevel@tonic-gate sqp = NULL; 1667*7c478bd9Sstevel@tonic-gate } 1668*7c478bd9Sstevel@tonic-gate break; 1669*7c478bd9Sstevel@tonic-gate 1670*7c478bd9Sstevel@tonic-gate case CLD_STOPPED: 1671*7c478bd9Sstevel@tonic-gate case CLD_CONTINUED: 1672*7c478bd9Sstevel@tonic-gate cv_broadcast(&pp->p_cv); 1673*7c478bd9Sstevel@tonic-gate if (pp->p_flag & SJCTL) { 1674*7c478bd9Sstevel@tonic-gate post_sigcld(cp, sqp); 1675*7c478bd9Sstevel@tonic-gate sqp = NULL; 1676*7c478bd9Sstevel@tonic-gate } 1677*7c478bd9Sstevel@tonic-gate break; 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate 1680*7c478bd9Sstevel@tonic-gate if (sqp) 1681*7c478bd9Sstevel@tonic-gate siginfofree(sqp); 1682*7c478bd9Sstevel@tonic-gate } 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate /* 1685*7c478bd9Sstevel@tonic-gate * Common code called from sigcld() and issig_forreal() 1686*7c478bd9Sstevel@tonic-gate * Give the parent process a SIGCLD if it does not have one pending, 1687*7c478bd9Sstevel@tonic-gate * else mark the child process so a SIGCLD can be posted later. 1688*7c478bd9Sstevel@tonic-gate */ 1689*7c478bd9Sstevel@tonic-gate static void 1690*7c478bd9Sstevel@tonic-gate post_sigcld(proc_t *cp, sigqueue_t *sqp) 1691*7c478bd9Sstevel@tonic-gate { 1692*7c478bd9Sstevel@tonic-gate proc_t *pp = cp->p_parent; 1693*7c478bd9Sstevel@tonic-gate void (*handler)() = PTOU(pp)->u_signal[SIGCLD - 1]; 1694*7c478bd9Sstevel@tonic-gate k_siginfo_t info; 1695*7c478bd9Sstevel@tonic-gate 1696*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 1697*7c478bd9Sstevel@tonic-gate mutex_enter(&pp->p_lock); 1698*7c478bd9Sstevel@tonic-gate 1699*7c478bd9Sstevel@tonic-gate /* 1700*7c478bd9Sstevel@tonic-gate * If a SIGCLD is pending, or if SIGCLD is not now being caught, 1701*7c478bd9Sstevel@tonic-gate * then just mark the child process so that its SIGCLD will 1702*7c478bd9Sstevel@tonic-gate * be posted later, when the first SIGCLD is taken off the 1703*7c478bd9Sstevel@tonic-gate * queue or when the parent is ready to receive it, if ever. 1704*7c478bd9Sstevel@tonic-gate */ 1705*7c478bd9Sstevel@tonic-gate if (handler == SIG_DFL || handler == SIG_IGN || 1706*7c478bd9Sstevel@tonic-gate sigismember(&pp->p_sig, SIGCLD)) 1707*7c478bd9Sstevel@tonic-gate cp->p_pidflag |= CLDPEND; 1708*7c478bd9Sstevel@tonic-gate else { 1709*7c478bd9Sstevel@tonic-gate cp->p_pidflag &= ~CLDPEND; 1710*7c478bd9Sstevel@tonic-gate if (sqp == NULL) { 1711*7c478bd9Sstevel@tonic-gate /* 1712*7c478bd9Sstevel@tonic-gate * This can only happen when the parent is init. 1713*7c478bd9Sstevel@tonic-gate * (See call to sigcld(q, NULL) in exit().) 1714*7c478bd9Sstevel@tonic-gate * Use KM_NOSLEEP to avoid deadlock. 1715*7c478bd9Sstevel@tonic-gate */ 1716*7c478bd9Sstevel@tonic-gate ASSERT(pp == proc_init); 1717*7c478bd9Sstevel@tonic-gate winfo(cp, &info, 0); 1718*7c478bd9Sstevel@tonic-gate sigaddq(pp, NULL, &info, KM_NOSLEEP); 1719*7c478bd9Sstevel@tonic-gate } else { 1720*7c478bd9Sstevel@tonic-gate winfo(cp, &sqp->sq_info, 0); 1721*7c478bd9Sstevel@tonic-gate sigaddqa(pp, NULL, sqp); 1722*7c478bd9Sstevel@tonic-gate sqp = NULL; 1723*7c478bd9Sstevel@tonic-gate } 1724*7c478bd9Sstevel@tonic-gate } 1725*7c478bd9Sstevel@tonic-gate 1726*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate if (sqp) 1729*7c478bd9Sstevel@tonic-gate siginfofree(sqp); 1730*7c478bd9Sstevel@tonic-gate } 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate /* 1733*7c478bd9Sstevel@tonic-gate * Search for a child that has a pending SIGCLD for us, the parent. 1734*7c478bd9Sstevel@tonic-gate * The queue of SIGCLD signals is implied by the list of children. 1735*7c478bd9Sstevel@tonic-gate * We post the SIGCLD signals one at a time so they don't get lost. 1736*7c478bd9Sstevel@tonic-gate * When one is dequeued, another is enqueued, until there are no more. 1737*7c478bd9Sstevel@tonic-gate */ 1738*7c478bd9Sstevel@tonic-gate void 1739*7c478bd9Sstevel@tonic-gate sigcld_repost() 1740*7c478bd9Sstevel@tonic-gate { 1741*7c478bd9Sstevel@tonic-gate proc_t *pp = curproc; 1742*7c478bd9Sstevel@tonic-gate proc_t *cp; 1743*7c478bd9Sstevel@tonic-gate void (*handler)() = PTOU(pp)->u_signal[SIGCLD - 1]; 1744*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 1745*7c478bd9Sstevel@tonic-gate 1746*7c478bd9Sstevel@tonic-gate /* 1747*7c478bd9Sstevel@tonic-gate * Don't bother if SIGCLD is not now being caught. 1748*7c478bd9Sstevel@tonic-gate */ 1749*7c478bd9Sstevel@tonic-gate if (handler == SIG_DFL || handler == SIG_IGN) 1750*7c478bd9Sstevel@tonic-gate return; 1751*7c478bd9Sstevel@tonic-gate 1752*7c478bd9Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); 1753*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 1754*7c478bd9Sstevel@tonic-gate for (cp = pp->p_child; cp; cp = cp->p_sibling) { 1755*7c478bd9Sstevel@tonic-gate if (cp->p_pidflag & CLDPEND) { 1756*7c478bd9Sstevel@tonic-gate post_sigcld(cp, sqp); 1757*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1758*7c478bd9Sstevel@tonic-gate return; 1759*7c478bd9Sstevel@tonic-gate } 1760*7c478bd9Sstevel@tonic-gate } 1761*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1762*7c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t)); 1763*7c478bd9Sstevel@tonic-gate } 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate /* 1766*7c478bd9Sstevel@tonic-gate * count number of sigqueue send by sigaddqa() 1767*7c478bd9Sstevel@tonic-gate */ 1768*7c478bd9Sstevel@tonic-gate void 1769*7c478bd9Sstevel@tonic-gate sigqsend(int cmd, proc_t *p, kthread_t *t, sigqueue_t *sigqp) 1770*7c478bd9Sstevel@tonic-gate { 1771*7c478bd9Sstevel@tonic-gate sigqhdr_t *sqh; 1772*7c478bd9Sstevel@tonic-gate 1773*7c478bd9Sstevel@tonic-gate sqh = (sigqhdr_t *)sigqp->sq_backptr; 1774*7c478bd9Sstevel@tonic-gate ASSERT(sqh); 1775*7c478bd9Sstevel@tonic-gate 1776*7c478bd9Sstevel@tonic-gate mutex_enter(&sqh->sqb_lock); 1777*7c478bd9Sstevel@tonic-gate sqh->sqb_sent++; 1778*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 1779*7c478bd9Sstevel@tonic-gate 1780*7c478bd9Sstevel@tonic-gate if (cmd == SN_SEND) 1781*7c478bd9Sstevel@tonic-gate sigaddqa(p, t, sigqp); 1782*7c478bd9Sstevel@tonic-gate else 1783*7c478bd9Sstevel@tonic-gate siginfofree(sigqp); 1784*7c478bd9Sstevel@tonic-gate } 1785*7c478bd9Sstevel@tonic-gate 1786*7c478bd9Sstevel@tonic-gate int 1787*7c478bd9Sstevel@tonic-gate sigsendproc(proc_t *p, sigsend_t *pv) 1788*7c478bd9Sstevel@tonic-gate { 1789*7c478bd9Sstevel@tonic-gate struct cred *cr; 1790*7c478bd9Sstevel@tonic-gate proc_t *myprocp = curproc; 1791*7c478bd9Sstevel@tonic-gate 1792*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate if (p->p_pid == 1 && pv->sig && sigismember(&cantmask, pv->sig)) 1795*7c478bd9Sstevel@tonic-gate return (EPERM); 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate cr = CRED(); 1798*7c478bd9Sstevel@tonic-gate 1799*7c478bd9Sstevel@tonic-gate if (pv->checkperm == 0 || 1800*7c478bd9Sstevel@tonic-gate (pv->sig == SIGCONT && p->p_sessp == myprocp->p_sessp) || 1801*7c478bd9Sstevel@tonic-gate prochasprocperm(p, myprocp, cr)) { 1802*7c478bd9Sstevel@tonic-gate pv->perm++; 1803*7c478bd9Sstevel@tonic-gate if (pv->sig) { 1804*7c478bd9Sstevel@tonic-gate /* Make sure we should be setting si_pid and friends */ 1805*7c478bd9Sstevel@tonic-gate ASSERT(pv->sicode <= 0); 1806*7c478bd9Sstevel@tonic-gate if (SI_CANQUEUE(pv->sicode)) { 1807*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate mutex_enter(&myprocp->p_lock); 1810*7c478bd9Sstevel@tonic-gate sqp = sigqalloc(myprocp->p_sigqhdr); 1811*7c478bd9Sstevel@tonic-gate mutex_exit(&myprocp->p_lock); 1812*7c478bd9Sstevel@tonic-gate if (sqp == NULL) 1813*7c478bd9Sstevel@tonic-gate return (EAGAIN); 1814*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_signo = pv->sig; 1815*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code = pv->sicode; 1816*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = myprocp->p_pid; 1817*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(myprocp); 1818*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 1819*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetruid(cr); 1820*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_value = pv->value; 1821*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1822*7c478bd9Sstevel@tonic-gate sigqsend(SN_SEND, p, NULL, sqp); 1823*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1824*7c478bd9Sstevel@tonic-gate } else { 1825*7c478bd9Sstevel@tonic-gate k_siginfo_t info; 1826*7c478bd9Sstevel@tonic-gate bzero(&info, sizeof (info)); 1827*7c478bd9Sstevel@tonic-gate info.si_signo = pv->sig; 1828*7c478bd9Sstevel@tonic-gate info.si_code = pv->sicode; 1829*7c478bd9Sstevel@tonic-gate info.si_pid = myprocp->p_pid; 1830*7c478bd9Sstevel@tonic-gate info.si_ctid = PRCTID(myprocp); 1831*7c478bd9Sstevel@tonic-gate info.si_zoneid = getzoneid(); 1832*7c478bd9Sstevel@tonic-gate info.si_uid = crgetruid(cr); 1833*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1834*7c478bd9Sstevel@tonic-gate /* 1835*7c478bd9Sstevel@tonic-gate * XXX: Should be KM_SLEEP but 1836*7c478bd9Sstevel@tonic-gate * we have to avoid deadlock. 1837*7c478bd9Sstevel@tonic-gate */ 1838*7c478bd9Sstevel@tonic-gate sigaddq(p, NULL, &info, KM_NOSLEEP); 1839*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1840*7c478bd9Sstevel@tonic-gate } 1841*7c478bd9Sstevel@tonic-gate } 1842*7c478bd9Sstevel@tonic-gate } 1843*7c478bd9Sstevel@tonic-gate 1844*7c478bd9Sstevel@tonic-gate return (0); 1845*7c478bd9Sstevel@tonic-gate } 1846*7c478bd9Sstevel@tonic-gate 1847*7c478bd9Sstevel@tonic-gate int 1848*7c478bd9Sstevel@tonic-gate sigsendset(procset_t *psp, sigsend_t *pv) 1849*7c478bd9Sstevel@tonic-gate { 1850*7c478bd9Sstevel@tonic-gate int error; 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate error = dotoprocs(psp, sigsendproc, (char *)pv); 1853*7c478bd9Sstevel@tonic-gate if (error == 0 && pv->perm == 0) 1854*7c478bd9Sstevel@tonic-gate return (EPERM); 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate return (error); 1857*7c478bd9Sstevel@tonic-gate } 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate /* 1860*7c478bd9Sstevel@tonic-gate * Dequeue a queued siginfo structure. 1861*7c478bd9Sstevel@tonic-gate * If a non-null thread pointer is passed then dequeue from 1862*7c478bd9Sstevel@tonic-gate * the thread queue, otherwise dequeue from the process queue. 1863*7c478bd9Sstevel@tonic-gate */ 1864*7c478bd9Sstevel@tonic-gate void 1865*7c478bd9Sstevel@tonic-gate sigdeq(proc_t *p, kthread_t *t, int sig, sigqueue_t **qpp) 1866*7c478bd9Sstevel@tonic-gate { 1867*7c478bd9Sstevel@tonic-gate sigqueue_t **psqp, *sqp; 1868*7c478bd9Sstevel@tonic-gate 1869*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate *qpp = NULL; 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate if (t != NULL) { 1874*7c478bd9Sstevel@tonic-gate sigdelset(&t->t_sig, sig); 1875*7c478bd9Sstevel@tonic-gate sigdelset(&t->t_extsig, sig); 1876*7c478bd9Sstevel@tonic-gate psqp = &t->t_sigqueue; 1877*7c478bd9Sstevel@tonic-gate } else { 1878*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_sig, sig); 1879*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_extsig, sig); 1880*7c478bd9Sstevel@tonic-gate psqp = &p->p_sigqueue; 1881*7c478bd9Sstevel@tonic-gate } 1882*7c478bd9Sstevel@tonic-gate 1883*7c478bd9Sstevel@tonic-gate for (;;) { 1884*7c478bd9Sstevel@tonic-gate if ((sqp = *psqp) == NULL) 1885*7c478bd9Sstevel@tonic-gate return; 1886*7c478bd9Sstevel@tonic-gate if (sqp->sq_info.si_signo == sig) 1887*7c478bd9Sstevel@tonic-gate break; 1888*7c478bd9Sstevel@tonic-gate else 1889*7c478bd9Sstevel@tonic-gate psqp = &sqp->sq_next; 1890*7c478bd9Sstevel@tonic-gate } 1891*7c478bd9Sstevel@tonic-gate *qpp = sqp; 1892*7c478bd9Sstevel@tonic-gate *psqp = sqp->sq_next; 1893*7c478bd9Sstevel@tonic-gate for (sqp = *psqp; sqp; sqp = sqp->sq_next) { 1894*7c478bd9Sstevel@tonic-gate if (sqp->sq_info.si_signo == sig) { 1895*7c478bd9Sstevel@tonic-gate if (t != (kthread_t *)NULL) { 1896*7c478bd9Sstevel@tonic-gate sigaddset(&t->t_sig, sig); 1897*7c478bd9Sstevel@tonic-gate t->t_sig_check = 1; 1898*7c478bd9Sstevel@tonic-gate } else { 1899*7c478bd9Sstevel@tonic-gate sigaddset(&p->p_sig, sig); 1900*7c478bd9Sstevel@tonic-gate set_proc_ast(p); 1901*7c478bd9Sstevel@tonic-gate } 1902*7c478bd9Sstevel@tonic-gate break; 1903*7c478bd9Sstevel@tonic-gate } 1904*7c478bd9Sstevel@tonic-gate } 1905*7c478bd9Sstevel@tonic-gate } 1906*7c478bd9Sstevel@tonic-gate 1907*7c478bd9Sstevel@tonic-gate /* 1908*7c478bd9Sstevel@tonic-gate * Delete a queued SIGCLD siginfo structure matching the k_siginfo_t argument. 1909*7c478bd9Sstevel@tonic-gate */ 1910*7c478bd9Sstevel@tonic-gate void 1911*7c478bd9Sstevel@tonic-gate sigcld_delete(k_siginfo_t *ip) 1912*7c478bd9Sstevel@tonic-gate { 1913*7c478bd9Sstevel@tonic-gate proc_t *p = curproc; 1914*7c478bd9Sstevel@tonic-gate int another_sigcld = 0; 1915*7c478bd9Sstevel@tonic-gate sigqueue_t **psqp, *sqp; 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate ASSERT(ip->si_signo == SIGCLD); 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate if (!sigismember(&p->p_sig, SIGCLD)) { 1922*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1923*7c478bd9Sstevel@tonic-gate return; 1924*7c478bd9Sstevel@tonic-gate } 1925*7c478bd9Sstevel@tonic-gate 1926*7c478bd9Sstevel@tonic-gate psqp = &p->p_sigqueue; 1927*7c478bd9Sstevel@tonic-gate for (;;) { 1928*7c478bd9Sstevel@tonic-gate if ((sqp = *psqp) == NULL) { 1929*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1930*7c478bd9Sstevel@tonic-gate return; 1931*7c478bd9Sstevel@tonic-gate } 1932*7c478bd9Sstevel@tonic-gate if (sqp->sq_info.si_signo == SIGCLD) { 1933*7c478bd9Sstevel@tonic-gate if (sqp->sq_info.si_pid == ip->si_pid && 1934*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_code == ip->si_code && 1935*7c478bd9Sstevel@tonic-gate sqp->sq_info.si_status == ip->si_status) 1936*7c478bd9Sstevel@tonic-gate break; 1937*7c478bd9Sstevel@tonic-gate another_sigcld = 1; 1938*7c478bd9Sstevel@tonic-gate } 1939*7c478bd9Sstevel@tonic-gate psqp = &sqp->sq_next; 1940*7c478bd9Sstevel@tonic-gate } 1941*7c478bd9Sstevel@tonic-gate *psqp = sqp->sq_next; 1942*7c478bd9Sstevel@tonic-gate 1943*7c478bd9Sstevel@tonic-gate siginfofree(sqp); 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate for (sqp = *psqp; !another_sigcld && sqp; sqp = sqp->sq_next) { 1946*7c478bd9Sstevel@tonic-gate if (sqp->sq_info.si_signo == SIGCLD) 1947*7c478bd9Sstevel@tonic-gate another_sigcld = 1; 1948*7c478bd9Sstevel@tonic-gate } 1949*7c478bd9Sstevel@tonic-gate 1950*7c478bd9Sstevel@tonic-gate if (!another_sigcld) { 1951*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_sig, SIGCLD); 1952*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_extsig, SIGCLD); 1953*7c478bd9Sstevel@tonic-gate } 1954*7c478bd9Sstevel@tonic-gate 1955*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1956*7c478bd9Sstevel@tonic-gate } 1957*7c478bd9Sstevel@tonic-gate 1958*7c478bd9Sstevel@tonic-gate /* 1959*7c478bd9Sstevel@tonic-gate * Delete queued siginfo structures. 1960*7c478bd9Sstevel@tonic-gate * If a non-null thread pointer is passed then delete from 1961*7c478bd9Sstevel@tonic-gate * the thread queue, otherwise delete from the process queue. 1962*7c478bd9Sstevel@tonic-gate */ 1963*7c478bd9Sstevel@tonic-gate void 1964*7c478bd9Sstevel@tonic-gate sigdelq(proc_t *p, kthread_t *t, int sig) 1965*7c478bd9Sstevel@tonic-gate { 1966*7c478bd9Sstevel@tonic-gate sigqueue_t **psqp, *sqp; 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate /* 1969*7c478bd9Sstevel@tonic-gate * We must be holding p->p_lock unless the process is 1970*7c478bd9Sstevel@tonic-gate * being reaped or has failed to get started on fork. 1971*7c478bd9Sstevel@tonic-gate */ 1972*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock) || 1973*7c478bd9Sstevel@tonic-gate p->p_stat == SIDL || p->p_stat == SZOMB); 1974*7c478bd9Sstevel@tonic-gate 1975*7c478bd9Sstevel@tonic-gate if (t != (kthread_t *)NULL) 1976*7c478bd9Sstevel@tonic-gate psqp = &t->t_sigqueue; 1977*7c478bd9Sstevel@tonic-gate else 1978*7c478bd9Sstevel@tonic-gate psqp = &p->p_sigqueue; 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate while (*psqp) { 1981*7c478bd9Sstevel@tonic-gate sqp = *psqp; 1982*7c478bd9Sstevel@tonic-gate if (sig == 0 || sqp->sq_info.si_signo == sig) { 1983*7c478bd9Sstevel@tonic-gate *psqp = sqp->sq_next; 1984*7c478bd9Sstevel@tonic-gate siginfofree(sqp); 1985*7c478bd9Sstevel@tonic-gate } else 1986*7c478bd9Sstevel@tonic-gate psqp = &sqp->sq_next; 1987*7c478bd9Sstevel@tonic-gate } 1988*7c478bd9Sstevel@tonic-gate } 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate /* 1991*7c478bd9Sstevel@tonic-gate * Insert a siginfo structure into a queue. 1992*7c478bd9Sstevel@tonic-gate * If a non-null thread pointer is passed then add to the thread queue, 1993*7c478bd9Sstevel@tonic-gate * otherwise add to the process queue. 1994*7c478bd9Sstevel@tonic-gate * 1995*7c478bd9Sstevel@tonic-gate * The function sigaddqins() is called with sigqueue already allocated. 1996*7c478bd9Sstevel@tonic-gate * It is called from sigaddqa() and sigaddq() below. 1997*7c478bd9Sstevel@tonic-gate * 1998*7c478bd9Sstevel@tonic-gate * The value of si_code implicitly indicates whether sigp is to be 1999*7c478bd9Sstevel@tonic-gate * explicitly queued, or to be queued to depth one. 2000*7c478bd9Sstevel@tonic-gate */ 2001*7c478bd9Sstevel@tonic-gate static void 2002*7c478bd9Sstevel@tonic-gate sigaddqins(proc_t *p, kthread_t *t, sigqueue_t *sigqp) 2003*7c478bd9Sstevel@tonic-gate { 2004*7c478bd9Sstevel@tonic-gate sigqueue_t **psqp; 2005*7c478bd9Sstevel@tonic-gate int sig = sigqp->sq_info.si_signo; 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate sigqp->sq_external = (curproc != &p0) && 2008*7c478bd9Sstevel@tonic-gate (curproc->p_ct_process != p->p_ct_process); 2009*7c478bd9Sstevel@tonic-gate 2010*7c478bd9Sstevel@tonic-gate /* 2011*7c478bd9Sstevel@tonic-gate * issig_forreal() doesn't bother dequeueing signals if SKILLED 2012*7c478bd9Sstevel@tonic-gate * is set, and even if it did, we would want to avoid situation 2013*7c478bd9Sstevel@tonic-gate * (which would be unique to SIGKILL) where one thread dequeued 2014*7c478bd9Sstevel@tonic-gate * the sigqueue_t and another executed psig(). So we create a 2015*7c478bd9Sstevel@tonic-gate * separate stash for SIGKILL's sigqueue_t. Because a second 2016*7c478bd9Sstevel@tonic-gate * SIGKILL can set SEXTKILLED, we overwrite the existing entry 2017*7c478bd9Sstevel@tonic-gate * if (and only if) it was non-extracontractual. 2018*7c478bd9Sstevel@tonic-gate */ 2019*7c478bd9Sstevel@tonic-gate if (sig == SIGKILL) { 2020*7c478bd9Sstevel@tonic-gate if (p->p_killsqp == NULL || !p->p_killsqp->sq_external) { 2021*7c478bd9Sstevel@tonic-gate if (p->p_killsqp != NULL) 2022*7c478bd9Sstevel@tonic-gate siginfofree(p->p_killsqp); 2023*7c478bd9Sstevel@tonic-gate p->p_killsqp = sigqp; 2024*7c478bd9Sstevel@tonic-gate sigqp->sq_next = NULL; 2025*7c478bd9Sstevel@tonic-gate } else { 2026*7c478bd9Sstevel@tonic-gate siginfofree(sigqp); 2027*7c478bd9Sstevel@tonic-gate } 2028*7c478bd9Sstevel@tonic-gate return; 2029*7c478bd9Sstevel@tonic-gate } 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate ASSERT(sig >= 1 && sig < NSIG); 2032*7c478bd9Sstevel@tonic-gate if (t != NULL) /* directed to a thread */ 2033*7c478bd9Sstevel@tonic-gate psqp = &t->t_sigqueue; 2034*7c478bd9Sstevel@tonic-gate else /* directed to a process */ 2035*7c478bd9Sstevel@tonic-gate psqp = &p->p_sigqueue; 2036*7c478bd9Sstevel@tonic-gate if (SI_CANQUEUE(sigqp->sq_info.si_code) && 2037*7c478bd9Sstevel@tonic-gate sigismember(&p->p_siginfo, sig)) { 2038*7c478bd9Sstevel@tonic-gate for (; *psqp != NULL; psqp = &(*psqp)->sq_next) 2039*7c478bd9Sstevel@tonic-gate ; 2040*7c478bd9Sstevel@tonic-gate } else { 2041*7c478bd9Sstevel@tonic-gate for (; *psqp != NULL; psqp = &(*psqp)->sq_next) { 2042*7c478bd9Sstevel@tonic-gate if ((*psqp)->sq_info.si_signo == sig) { 2043*7c478bd9Sstevel@tonic-gate siginfofree(sigqp); 2044*7c478bd9Sstevel@tonic-gate return; 2045*7c478bd9Sstevel@tonic-gate } 2046*7c478bd9Sstevel@tonic-gate } 2047*7c478bd9Sstevel@tonic-gate } 2048*7c478bd9Sstevel@tonic-gate *psqp = sigqp; 2049*7c478bd9Sstevel@tonic-gate sigqp->sq_next = NULL; 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate /* 2053*7c478bd9Sstevel@tonic-gate * The function sigaddqa() is called with sigqueue already allocated. 2054*7c478bd9Sstevel@tonic-gate * If signal is ignored, discard but guarantee KILL and generation semantics. 2055*7c478bd9Sstevel@tonic-gate * It is called from sigqueue() and other places. 2056*7c478bd9Sstevel@tonic-gate */ 2057*7c478bd9Sstevel@tonic-gate void 2058*7c478bd9Sstevel@tonic-gate sigaddqa(proc_t *p, kthread_t *t, sigqueue_t *sigqp) 2059*7c478bd9Sstevel@tonic-gate { 2060*7c478bd9Sstevel@tonic-gate int sig = sigqp->sq_info.si_signo; 2061*7c478bd9Sstevel@tonic-gate 2062*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 2063*7c478bd9Sstevel@tonic-gate ASSERT(sig >= 1 && sig < NSIG); 2064*7c478bd9Sstevel@tonic-gate 2065*7c478bd9Sstevel@tonic-gate if (sig_discardable(p, sig)) 2066*7c478bd9Sstevel@tonic-gate siginfofree(sigqp); 2067*7c478bd9Sstevel@tonic-gate else 2068*7c478bd9Sstevel@tonic-gate sigaddqins(p, t, sigqp); 2069*7c478bd9Sstevel@tonic-gate 2070*7c478bd9Sstevel@tonic-gate sigtoproc(p, t, sig); 2071*7c478bd9Sstevel@tonic-gate } 2072*7c478bd9Sstevel@tonic-gate 2073*7c478bd9Sstevel@tonic-gate /* 2074*7c478bd9Sstevel@tonic-gate * Allocate the sigqueue_t structure and call sigaddqins(). 2075*7c478bd9Sstevel@tonic-gate */ 2076*7c478bd9Sstevel@tonic-gate void 2077*7c478bd9Sstevel@tonic-gate sigaddq(proc_t *p, kthread_t *t, k_siginfo_t *infop, int km_flags) 2078*7c478bd9Sstevel@tonic-gate { 2079*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 2080*7c478bd9Sstevel@tonic-gate int sig = infop->si_signo; 2081*7c478bd9Sstevel@tonic-gate 2082*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 2083*7c478bd9Sstevel@tonic-gate ASSERT(sig >= 1 && sig < NSIG); 2084*7c478bd9Sstevel@tonic-gate 2085*7c478bd9Sstevel@tonic-gate /* 2086*7c478bd9Sstevel@tonic-gate * If the signal will be discarded by sigtoproc() or 2087*7c478bd9Sstevel@tonic-gate * if the process isn't requesting siginfo and it isn't 2088*7c478bd9Sstevel@tonic-gate * blocking the signal (it *could* change it's mind while 2089*7c478bd9Sstevel@tonic-gate * the signal is pending) then don't bother creating one. 2090*7c478bd9Sstevel@tonic-gate */ 2091*7c478bd9Sstevel@tonic-gate if (!sig_discardable(p, sig) && 2092*7c478bd9Sstevel@tonic-gate (sigismember(&p->p_siginfo, sig) || 2093*7c478bd9Sstevel@tonic-gate (curproc->p_ct_process != p->p_ct_process) || 2094*7c478bd9Sstevel@tonic-gate (sig == SIGCLD && SI_FROMKERNEL(infop))) && 2095*7c478bd9Sstevel@tonic-gate ((sqp = kmem_alloc(sizeof (sigqueue_t), km_flags)) != NULL)) { 2096*7c478bd9Sstevel@tonic-gate bcopy(infop, &sqp->sq_info, sizeof (k_siginfo_t)); 2097*7c478bd9Sstevel@tonic-gate sqp->sq_func = NULL; 2098*7c478bd9Sstevel@tonic-gate sqp->sq_next = NULL; 2099*7c478bd9Sstevel@tonic-gate sigaddqins(p, t, sqp); 2100*7c478bd9Sstevel@tonic-gate } 2101*7c478bd9Sstevel@tonic-gate sigtoproc(p, t, sig); 2102*7c478bd9Sstevel@tonic-gate } 2103*7c478bd9Sstevel@tonic-gate 2104*7c478bd9Sstevel@tonic-gate /* 2105*7c478bd9Sstevel@tonic-gate * Handle stop-on-fault processing for the debugger. Returns 0 2106*7c478bd9Sstevel@tonic-gate * if the fault is cleared during the stop, nonzero if it isn't. 2107*7c478bd9Sstevel@tonic-gate */ 2108*7c478bd9Sstevel@tonic-gate int 2109*7c478bd9Sstevel@tonic-gate stop_on_fault(uint_t fault, k_siginfo_t *sip) 2110*7c478bd9Sstevel@tonic-gate { 2111*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 2112*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 2113*7c478bd9Sstevel@tonic-gate 2114*7c478bd9Sstevel@tonic-gate ASSERT(prismember(&p->p_fltmask, fault)); 2115*7c478bd9Sstevel@tonic-gate 2116*7c478bd9Sstevel@tonic-gate /* 2117*7c478bd9Sstevel@tonic-gate * Record current fault and siginfo structure so debugger can 2118*7c478bd9Sstevel@tonic-gate * find it. 2119*7c478bd9Sstevel@tonic-gate */ 2120*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2121*7c478bd9Sstevel@tonic-gate lwp->lwp_curflt = (uchar_t)fault; 2122*7c478bd9Sstevel@tonic-gate lwp->lwp_siginfo = *sip; 2123*7c478bd9Sstevel@tonic-gate 2124*7c478bd9Sstevel@tonic-gate stop(PR_FAULTED, fault); 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate fault = lwp->lwp_curflt; 2127*7c478bd9Sstevel@tonic-gate lwp->lwp_curflt = 0; 2128*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2129*7c478bd9Sstevel@tonic-gate return (fault); 2130*7c478bd9Sstevel@tonic-gate } 2131*7c478bd9Sstevel@tonic-gate 2132*7c478bd9Sstevel@tonic-gate void 2133*7c478bd9Sstevel@tonic-gate sigorset(k_sigset_t *s1, k_sigset_t *s2) 2134*7c478bd9Sstevel@tonic-gate { 2135*7c478bd9Sstevel@tonic-gate s1->__sigbits[0] |= s2->__sigbits[0]; 2136*7c478bd9Sstevel@tonic-gate s1->__sigbits[1] |= s2->__sigbits[1]; 2137*7c478bd9Sstevel@tonic-gate } 2138*7c478bd9Sstevel@tonic-gate 2139*7c478bd9Sstevel@tonic-gate void 2140*7c478bd9Sstevel@tonic-gate sigandset(k_sigset_t *s1, k_sigset_t *s2) 2141*7c478bd9Sstevel@tonic-gate { 2142*7c478bd9Sstevel@tonic-gate s1->__sigbits[0] &= s2->__sigbits[0]; 2143*7c478bd9Sstevel@tonic-gate s1->__sigbits[1] &= s2->__sigbits[1]; 2144*7c478bd9Sstevel@tonic-gate } 2145*7c478bd9Sstevel@tonic-gate 2146*7c478bd9Sstevel@tonic-gate void 2147*7c478bd9Sstevel@tonic-gate sigdiffset(k_sigset_t *s1, k_sigset_t *s2) 2148*7c478bd9Sstevel@tonic-gate { 2149*7c478bd9Sstevel@tonic-gate s1->__sigbits[0] &= ~(s2->__sigbits[0]); 2150*7c478bd9Sstevel@tonic-gate s1->__sigbits[1] &= ~(s2->__sigbits[1]); 2151*7c478bd9Sstevel@tonic-gate } 2152*7c478bd9Sstevel@tonic-gate 2153*7c478bd9Sstevel@tonic-gate /* 2154*7c478bd9Sstevel@tonic-gate * Return non-zero if curthread->t_sig_check should be set to 1, that is, 2155*7c478bd9Sstevel@tonic-gate * if there are any signals the thread might take on return from the kernel. 2156*7c478bd9Sstevel@tonic-gate * If ksigset_t's were a single word, we would do: 2157*7c478bd9Sstevel@tonic-gate * return (((p->p_sig | t->t_sig) & ~t->t_hold) & fillset); 2158*7c478bd9Sstevel@tonic-gate */ 2159*7c478bd9Sstevel@tonic-gate int 2160*7c478bd9Sstevel@tonic-gate sigcheck(proc_t *p, kthread_t *t) 2161*7c478bd9Sstevel@tonic-gate { 2162*7c478bd9Sstevel@tonic-gate sc_shared_t *tdp = t->t_schedctl; 2163*7c478bd9Sstevel@tonic-gate 2164*7c478bd9Sstevel@tonic-gate /* 2165*7c478bd9Sstevel@tonic-gate * If signals are blocked via the schedctl interface 2166*7c478bd9Sstevel@tonic-gate * then we only check for the unmaskable signals. 2167*7c478bd9Sstevel@tonic-gate */ 2168*7c478bd9Sstevel@tonic-gate if (tdp != NULL && tdp->sc_sigblock) 2169*7c478bd9Sstevel@tonic-gate return ((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) & 2170*7c478bd9Sstevel@tonic-gate CANTMASK0); 2171*7c478bd9Sstevel@tonic-gate 2172*7c478bd9Sstevel@tonic-gate return (((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) & 2173*7c478bd9Sstevel@tonic-gate ~t->t_hold.__sigbits[0]) | 2174*7c478bd9Sstevel@tonic-gate (((p->p_sig.__sigbits[1] | t->t_sig.__sigbits[1]) & 2175*7c478bd9Sstevel@tonic-gate ~t->t_hold.__sigbits[1]) & FILLSET1)); 2176*7c478bd9Sstevel@tonic-gate } 2177*7c478bd9Sstevel@tonic-gate 2178*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 2179*7c478bd9Sstevel@tonic-gate void 2180*7c478bd9Sstevel@tonic-gate sigintr(k_sigset_t *smask, int intable) 2181*7c478bd9Sstevel@tonic-gate { 2182*7c478bd9Sstevel@tonic-gate proc_t *p; 2183*7c478bd9Sstevel@tonic-gate int owned; 2184*7c478bd9Sstevel@tonic-gate k_sigset_t lmask; /* local copy of cantmask */ 2185*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 2186*7c478bd9Sstevel@tonic-gate 2187*7c478bd9Sstevel@tonic-gate /* 2188*7c478bd9Sstevel@tonic-gate * Mask out all signals except SIGHUP, SIGINT, SIGQUIT 2189*7c478bd9Sstevel@tonic-gate * and SIGTERM. (Preserving the existing masks). 2190*7c478bd9Sstevel@tonic-gate * This function supports the -intr nfs and ufs mount option. 2191*7c478bd9Sstevel@tonic-gate */ 2192*7c478bd9Sstevel@tonic-gate 2193*7c478bd9Sstevel@tonic-gate /* 2194*7c478bd9Sstevel@tonic-gate * don't do kernel threads 2195*7c478bd9Sstevel@tonic-gate */ 2196*7c478bd9Sstevel@tonic-gate if (lwp == NULL) 2197*7c478bd9Sstevel@tonic-gate return; 2198*7c478bd9Sstevel@tonic-gate 2199*7c478bd9Sstevel@tonic-gate /* 2200*7c478bd9Sstevel@tonic-gate * get access to signal mask 2201*7c478bd9Sstevel@tonic-gate */ 2202*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 2203*7c478bd9Sstevel@tonic-gate owned = mutex_owned(&p->p_lock); /* this is filthy */ 2204*7c478bd9Sstevel@tonic-gate if (!owned) 2205*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2206*7c478bd9Sstevel@tonic-gate 2207*7c478bd9Sstevel@tonic-gate /* 2208*7c478bd9Sstevel@tonic-gate * remember the current mask 2209*7c478bd9Sstevel@tonic-gate */ 2210*7c478bd9Sstevel@tonic-gate schedctl_finish_sigblock(curthread); 2211*7c478bd9Sstevel@tonic-gate *smask = curthread->t_hold; 2212*7c478bd9Sstevel@tonic-gate 2213*7c478bd9Sstevel@tonic-gate /* 2214*7c478bd9Sstevel@tonic-gate * mask out all signals 2215*7c478bd9Sstevel@tonic-gate */ 2216*7c478bd9Sstevel@tonic-gate sigfillset(&curthread->t_hold); 2217*7c478bd9Sstevel@tonic-gate 2218*7c478bd9Sstevel@tonic-gate /* 2219*7c478bd9Sstevel@tonic-gate * Unmask the non-maskable signals (e.g., KILL), as long as 2220*7c478bd9Sstevel@tonic-gate * they aren't already masked (which could happen at exit). 2221*7c478bd9Sstevel@tonic-gate * The first sigdiffset sets lmask to (cantmask & ~curhold). The 2222*7c478bd9Sstevel@tonic-gate * second sets the current hold mask to (~0 & ~lmask), which reduces 2223*7c478bd9Sstevel@tonic-gate * to (~cantmask | curhold). 2224*7c478bd9Sstevel@tonic-gate */ 2225*7c478bd9Sstevel@tonic-gate lmask = cantmask; 2226*7c478bd9Sstevel@tonic-gate sigdiffset(&lmask, smask); 2227*7c478bd9Sstevel@tonic-gate sigdiffset(&curthread->t_hold, &lmask); 2228*7c478bd9Sstevel@tonic-gate 2229*7c478bd9Sstevel@tonic-gate /* 2230*7c478bd9Sstevel@tonic-gate * Re-enable HUP, QUIT, and TERM iff they were originally enabled 2231*7c478bd9Sstevel@tonic-gate * Re-enable INT if it's originally enabled and the NFS mount option 2232*7c478bd9Sstevel@tonic-gate * nointr is not set. 2233*7c478bd9Sstevel@tonic-gate */ 2234*7c478bd9Sstevel@tonic-gate if (!sigismember(smask, SIGHUP)) 2235*7c478bd9Sstevel@tonic-gate sigdelset(&curthread->t_hold, SIGHUP); 2236*7c478bd9Sstevel@tonic-gate if (!sigismember(smask, SIGINT) && intable) 2237*7c478bd9Sstevel@tonic-gate sigdelset(&curthread->t_hold, SIGINT); 2238*7c478bd9Sstevel@tonic-gate if (!sigismember(smask, SIGQUIT)) 2239*7c478bd9Sstevel@tonic-gate sigdelset(&curthread->t_hold, SIGQUIT); 2240*7c478bd9Sstevel@tonic-gate if (!sigismember(smask, SIGTERM)) 2241*7c478bd9Sstevel@tonic-gate sigdelset(&curthread->t_hold, SIGTERM); 2242*7c478bd9Sstevel@tonic-gate 2243*7c478bd9Sstevel@tonic-gate /* 2244*7c478bd9Sstevel@tonic-gate * release access to signal mask 2245*7c478bd9Sstevel@tonic-gate */ 2246*7c478bd9Sstevel@tonic-gate if (!owned) 2247*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2248*7c478bd9Sstevel@tonic-gate 2249*7c478bd9Sstevel@tonic-gate /* 2250*7c478bd9Sstevel@tonic-gate * Indicate that this lwp is not to be stopped. 2251*7c478bd9Sstevel@tonic-gate */ 2252*7c478bd9Sstevel@tonic-gate lwp->lwp_nostop++; 2253*7c478bd9Sstevel@tonic-gate 2254*7c478bd9Sstevel@tonic-gate } 2255*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 2256*7c478bd9Sstevel@tonic-gate 2257*7c478bd9Sstevel@tonic-gate void 2258*7c478bd9Sstevel@tonic-gate sigunintr(k_sigset_t *smask) 2259*7c478bd9Sstevel@tonic-gate { 2260*7c478bd9Sstevel@tonic-gate proc_t *p; 2261*7c478bd9Sstevel@tonic-gate int owned; 2262*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 2263*7c478bd9Sstevel@tonic-gate 2264*7c478bd9Sstevel@tonic-gate /* 2265*7c478bd9Sstevel@tonic-gate * Reset previous mask (See sigintr() above) 2266*7c478bd9Sstevel@tonic-gate */ 2267*7c478bd9Sstevel@tonic-gate if (lwp != NULL) { 2268*7c478bd9Sstevel@tonic-gate lwp->lwp_nostop--; /* restore lwp stoppability */ 2269*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 2270*7c478bd9Sstevel@tonic-gate owned = mutex_owned(&p->p_lock); /* this is filthy */ 2271*7c478bd9Sstevel@tonic-gate if (!owned) 2272*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2273*7c478bd9Sstevel@tonic-gate curthread->t_hold = *smask; 2274*7c478bd9Sstevel@tonic-gate /* so unmasked signals will be seen */ 2275*7c478bd9Sstevel@tonic-gate curthread->t_sig_check = 1; 2276*7c478bd9Sstevel@tonic-gate if (!owned) 2277*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2278*7c478bd9Sstevel@tonic-gate } 2279*7c478bd9Sstevel@tonic-gate } 2280*7c478bd9Sstevel@tonic-gate 2281*7c478bd9Sstevel@tonic-gate void 2282*7c478bd9Sstevel@tonic-gate sigreplace(k_sigset_t *newmask, k_sigset_t *oldmask) 2283*7c478bd9Sstevel@tonic-gate { 2284*7c478bd9Sstevel@tonic-gate proc_t *p; 2285*7c478bd9Sstevel@tonic-gate int owned; 2286*7c478bd9Sstevel@tonic-gate /* 2287*7c478bd9Sstevel@tonic-gate * Save current signal mask in oldmask, then 2288*7c478bd9Sstevel@tonic-gate * set it to newmask. 2289*7c478bd9Sstevel@tonic-gate */ 2290*7c478bd9Sstevel@tonic-gate if (ttolwp(curthread) != NULL) { 2291*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 2292*7c478bd9Sstevel@tonic-gate owned = mutex_owned(&p->p_lock); /* this is filthy */ 2293*7c478bd9Sstevel@tonic-gate if (!owned) 2294*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2295*7c478bd9Sstevel@tonic-gate schedctl_finish_sigblock(curthread); 2296*7c478bd9Sstevel@tonic-gate if (oldmask != NULL) 2297*7c478bd9Sstevel@tonic-gate *oldmask = curthread->t_hold; 2298*7c478bd9Sstevel@tonic-gate curthread->t_hold = *newmask; 2299*7c478bd9Sstevel@tonic-gate curthread->t_sig_check = 1; 2300*7c478bd9Sstevel@tonic-gate if (!owned) 2301*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2302*7c478bd9Sstevel@tonic-gate } 2303*7c478bd9Sstevel@tonic-gate } 2304*7c478bd9Sstevel@tonic-gate 2305*7c478bd9Sstevel@tonic-gate /* 2306*7c478bd9Sstevel@tonic-gate * Return true if the signal number is in range 2307*7c478bd9Sstevel@tonic-gate * and the signal code specifies signal queueing. 2308*7c478bd9Sstevel@tonic-gate */ 2309*7c478bd9Sstevel@tonic-gate int 2310*7c478bd9Sstevel@tonic-gate sigwillqueue(int sig, int code) 2311*7c478bd9Sstevel@tonic-gate { 2312*7c478bd9Sstevel@tonic-gate if (sig >= 0 && sig < NSIG) { 2313*7c478bd9Sstevel@tonic-gate switch (code) { 2314*7c478bd9Sstevel@tonic-gate case SI_QUEUE: 2315*7c478bd9Sstevel@tonic-gate case SI_TIMER: 2316*7c478bd9Sstevel@tonic-gate case SI_ASYNCIO: 2317*7c478bd9Sstevel@tonic-gate case SI_MESGQ: 2318*7c478bd9Sstevel@tonic-gate return (1); 2319*7c478bd9Sstevel@tonic-gate } 2320*7c478bd9Sstevel@tonic-gate } 2321*7c478bd9Sstevel@tonic-gate return (0); 2322*7c478bd9Sstevel@tonic-gate } 2323*7c478bd9Sstevel@tonic-gate 2324*7c478bd9Sstevel@tonic-gate #ifndef UCHAR_MAX 2325*7c478bd9Sstevel@tonic-gate #define UCHAR_MAX 255 2326*7c478bd9Sstevel@tonic-gate #endif 2327*7c478bd9Sstevel@tonic-gate 2328*7c478bd9Sstevel@tonic-gate /* 2329*7c478bd9Sstevel@tonic-gate * The entire pool (with maxcount entries) is pre-allocated at 2330*7c478bd9Sstevel@tonic-gate * the first sigqueue/signotify call. 2331*7c478bd9Sstevel@tonic-gate */ 2332*7c478bd9Sstevel@tonic-gate sigqhdr_t * 2333*7c478bd9Sstevel@tonic-gate sigqhdralloc(size_t size, uint_t maxcount) 2334*7c478bd9Sstevel@tonic-gate { 2335*7c478bd9Sstevel@tonic-gate size_t i; 2336*7c478bd9Sstevel@tonic-gate sigqueue_t *sq, *next; 2337*7c478bd9Sstevel@tonic-gate sigqhdr_t *sqh; 2338*7c478bd9Sstevel@tonic-gate 2339*7c478bd9Sstevel@tonic-gate i = (maxcount * size) + sizeof (sigqhdr_t); 2340*7c478bd9Sstevel@tonic-gate ASSERT(maxcount <= UCHAR_MAX && i <= USHRT_MAX); 2341*7c478bd9Sstevel@tonic-gate sqh = kmem_alloc(i, KM_SLEEP); 2342*7c478bd9Sstevel@tonic-gate sqh->sqb_count = (uchar_t)maxcount; 2343*7c478bd9Sstevel@tonic-gate sqh->sqb_maxcount = (uchar_t)maxcount; 2344*7c478bd9Sstevel@tonic-gate sqh->sqb_size = (ushort_t)i; 2345*7c478bd9Sstevel@tonic-gate sqh->sqb_pexited = 0; 2346*7c478bd9Sstevel@tonic-gate sqh->sqb_sent = 0; 2347*7c478bd9Sstevel@tonic-gate sqh->sqb_free = sq = (sigqueue_t *)(sqh + 1); 2348*7c478bd9Sstevel@tonic-gate for (i = maxcount - 1; i != 0; i--) { 2349*7c478bd9Sstevel@tonic-gate next = (sigqueue_t *)((uintptr_t)sq + size); 2350*7c478bd9Sstevel@tonic-gate sq->sq_next = next; 2351*7c478bd9Sstevel@tonic-gate sq = next; 2352*7c478bd9Sstevel@tonic-gate } 2353*7c478bd9Sstevel@tonic-gate sq->sq_next = NULL; 2354*7c478bd9Sstevel@tonic-gate mutex_init(&sqh->sqb_lock, NULL, MUTEX_DEFAULT, NULL); 2355*7c478bd9Sstevel@tonic-gate return (sqh); 2356*7c478bd9Sstevel@tonic-gate } 2357*7c478bd9Sstevel@tonic-gate 2358*7c478bd9Sstevel@tonic-gate static void sigqrel(sigqueue_t *); 2359*7c478bd9Sstevel@tonic-gate 2360*7c478bd9Sstevel@tonic-gate /* 2361*7c478bd9Sstevel@tonic-gate * allocate a sigqueue/signotify structure from the per process 2362*7c478bd9Sstevel@tonic-gate * pre-allocated pool. 2363*7c478bd9Sstevel@tonic-gate */ 2364*7c478bd9Sstevel@tonic-gate sigqueue_t * 2365*7c478bd9Sstevel@tonic-gate sigqalloc(sigqhdr_t *sqh) 2366*7c478bd9Sstevel@tonic-gate { 2367*7c478bd9Sstevel@tonic-gate sigqueue_t *sq = NULL; 2368*7c478bd9Sstevel@tonic-gate 2369*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&curproc->p_lock)); 2370*7c478bd9Sstevel@tonic-gate 2371*7c478bd9Sstevel@tonic-gate if (sqh != NULL) { 2372*7c478bd9Sstevel@tonic-gate mutex_enter(&sqh->sqb_lock); 2373*7c478bd9Sstevel@tonic-gate if (sqh->sqb_count > 0) { 2374*7c478bd9Sstevel@tonic-gate sqh->sqb_count--; 2375*7c478bd9Sstevel@tonic-gate sq = sqh->sqb_free; 2376*7c478bd9Sstevel@tonic-gate sqh->sqb_free = sq->sq_next; 2377*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 2378*7c478bd9Sstevel@tonic-gate bzero(&sq->sq_info, sizeof (k_siginfo_t)); 2379*7c478bd9Sstevel@tonic-gate sq->sq_backptr = sqh; 2380*7c478bd9Sstevel@tonic-gate sq->sq_func = sigqrel; 2381*7c478bd9Sstevel@tonic-gate sq->sq_next = NULL; 2382*7c478bd9Sstevel@tonic-gate sq->sq_external = 0; 2383*7c478bd9Sstevel@tonic-gate } else { 2384*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 2385*7c478bd9Sstevel@tonic-gate } 2386*7c478bd9Sstevel@tonic-gate } 2387*7c478bd9Sstevel@tonic-gate return (sq); 2388*7c478bd9Sstevel@tonic-gate } 2389*7c478bd9Sstevel@tonic-gate 2390*7c478bd9Sstevel@tonic-gate /* 2391*7c478bd9Sstevel@tonic-gate * Return a sigqueue structure back to the pre-allocated pool. 2392*7c478bd9Sstevel@tonic-gate */ 2393*7c478bd9Sstevel@tonic-gate static void 2394*7c478bd9Sstevel@tonic-gate sigqrel(sigqueue_t *sq) 2395*7c478bd9Sstevel@tonic-gate { 2396*7c478bd9Sstevel@tonic-gate sigqhdr_t *sqh; 2397*7c478bd9Sstevel@tonic-gate 2398*7c478bd9Sstevel@tonic-gate /* make sure that p_lock of the affected process is held */ 2399*7c478bd9Sstevel@tonic-gate 2400*7c478bd9Sstevel@tonic-gate sqh = (sigqhdr_t *)sq->sq_backptr; 2401*7c478bd9Sstevel@tonic-gate mutex_enter(&sqh->sqb_lock); 2402*7c478bd9Sstevel@tonic-gate if (sqh->sqb_pexited && sqh->sqb_sent == 1) { 2403*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 2404*7c478bd9Sstevel@tonic-gate mutex_destroy(&sqh->sqb_lock); 2405*7c478bd9Sstevel@tonic-gate kmem_free(sqh, sqh->sqb_size); 2406*7c478bd9Sstevel@tonic-gate } else { 2407*7c478bd9Sstevel@tonic-gate sqh->sqb_count++; 2408*7c478bd9Sstevel@tonic-gate sqh->sqb_sent--; 2409*7c478bd9Sstevel@tonic-gate sq->sq_next = sqh->sqb_free; 2410*7c478bd9Sstevel@tonic-gate sq->sq_backptr = NULL; 2411*7c478bd9Sstevel@tonic-gate sqh->sqb_free = sq; 2412*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 2413*7c478bd9Sstevel@tonic-gate } 2414*7c478bd9Sstevel@tonic-gate } 2415*7c478bd9Sstevel@tonic-gate 2416*7c478bd9Sstevel@tonic-gate /* 2417*7c478bd9Sstevel@tonic-gate * Free up the pre-allocated sigqueue headers of sigqueue pool 2418*7c478bd9Sstevel@tonic-gate * and signotify pool, if possible. 2419*7c478bd9Sstevel@tonic-gate * Called only by the owning process during exec() and exit(). 2420*7c478bd9Sstevel@tonic-gate */ 2421*7c478bd9Sstevel@tonic-gate void 2422*7c478bd9Sstevel@tonic-gate sigqfree(proc_t *p) 2423*7c478bd9Sstevel@tonic-gate { 2424*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 2425*7c478bd9Sstevel@tonic-gate 2426*7c478bd9Sstevel@tonic-gate if (p->p_sigqhdr != NULL) { /* sigqueue pool */ 2427*7c478bd9Sstevel@tonic-gate sigqhdrfree(p->p_sigqhdr); 2428*7c478bd9Sstevel@tonic-gate p->p_sigqhdr = NULL; 2429*7c478bd9Sstevel@tonic-gate } 2430*7c478bd9Sstevel@tonic-gate if (p->p_signhdr != NULL) { /* signotify pool */ 2431*7c478bd9Sstevel@tonic-gate sigqhdrfree(p->p_signhdr); 2432*7c478bd9Sstevel@tonic-gate p->p_signhdr = NULL; 2433*7c478bd9Sstevel@tonic-gate } 2434*7c478bd9Sstevel@tonic-gate } 2435*7c478bd9Sstevel@tonic-gate 2436*7c478bd9Sstevel@tonic-gate /* 2437*7c478bd9Sstevel@tonic-gate * Free up the pre-allocated header and sigq pool if possible. 2438*7c478bd9Sstevel@tonic-gate */ 2439*7c478bd9Sstevel@tonic-gate void 2440*7c478bd9Sstevel@tonic-gate sigqhdrfree(sigqhdr_t *sqh) 2441*7c478bd9Sstevel@tonic-gate { 2442*7c478bd9Sstevel@tonic-gate mutex_enter(&sqh->sqb_lock); 2443*7c478bd9Sstevel@tonic-gate if (sqh->sqb_sent == 0) { 2444*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 2445*7c478bd9Sstevel@tonic-gate mutex_destroy(&sqh->sqb_lock); 2446*7c478bd9Sstevel@tonic-gate kmem_free(sqh, sqh->sqb_size); 2447*7c478bd9Sstevel@tonic-gate } else { 2448*7c478bd9Sstevel@tonic-gate sqh->sqb_pexited = 1; 2449*7c478bd9Sstevel@tonic-gate mutex_exit(&sqh->sqb_lock); 2450*7c478bd9Sstevel@tonic-gate } 2451*7c478bd9Sstevel@tonic-gate } 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate /* 2454*7c478bd9Sstevel@tonic-gate * Free up a single sigqueue structure. 2455*7c478bd9Sstevel@tonic-gate * No other code should free a sigqueue directly. 2456*7c478bd9Sstevel@tonic-gate */ 2457*7c478bd9Sstevel@tonic-gate void 2458*7c478bd9Sstevel@tonic-gate siginfofree(sigqueue_t *sqp) 2459*7c478bd9Sstevel@tonic-gate { 2460*7c478bd9Sstevel@tonic-gate if (sqp != NULL) { 2461*7c478bd9Sstevel@tonic-gate if (sqp->sq_func != NULL) 2462*7c478bd9Sstevel@tonic-gate (sqp->sq_func)(sqp); 2463*7c478bd9Sstevel@tonic-gate else 2464*7c478bd9Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t)); 2465*7c478bd9Sstevel@tonic-gate } 2466*7c478bd9Sstevel@tonic-gate } 2467*7c478bd9Sstevel@tonic-gate 2468*7c478bd9Sstevel@tonic-gate /* 2469*7c478bd9Sstevel@tonic-gate * Generate a synchronous signal caused by a hardware 2470*7c478bd9Sstevel@tonic-gate * condition encountered by an lwp. Called from trap(). 2471*7c478bd9Sstevel@tonic-gate */ 2472*7c478bd9Sstevel@tonic-gate void 2473*7c478bd9Sstevel@tonic-gate trapsig(k_siginfo_t *ip, int restartable) 2474*7c478bd9Sstevel@tonic-gate { 2475*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 2476*7c478bd9Sstevel@tonic-gate int sig = ip->si_signo; 2477*7c478bd9Sstevel@tonic-gate sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); 2478*7c478bd9Sstevel@tonic-gate 2479*7c478bd9Sstevel@tonic-gate ASSERT(sig > 0 && sig < NSIG); 2480*7c478bd9Sstevel@tonic-gate 2481*7c478bd9Sstevel@tonic-gate if (curthread->t_dtrace_on) 2482*7c478bd9Sstevel@tonic-gate dtrace_safe_synchronous_signal(); 2483*7c478bd9Sstevel@tonic-gate 2484*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2485*7c478bd9Sstevel@tonic-gate schedctl_finish_sigblock(curthread); 2486*7c478bd9Sstevel@tonic-gate /* 2487*7c478bd9Sstevel@tonic-gate * Avoid a possible infinite loop if the lwp is holding the 2488*7c478bd9Sstevel@tonic-gate * signal generated by a trap of a restartable instruction or 2489*7c478bd9Sstevel@tonic-gate * if the signal so generated is being ignored by the process. 2490*7c478bd9Sstevel@tonic-gate */ 2491*7c478bd9Sstevel@tonic-gate if (restartable && 2492*7c478bd9Sstevel@tonic-gate (sigismember(&curthread->t_hold, sig) || 2493*7c478bd9Sstevel@tonic-gate p->p_user.u_signal[sig-1] == SIG_IGN)) { 2494*7c478bd9Sstevel@tonic-gate sigdelset(&curthread->t_hold, sig); 2495*7c478bd9Sstevel@tonic-gate p->p_user.u_signal[sig-1] = SIG_DFL; 2496*7c478bd9Sstevel@tonic-gate sigdelset(&p->p_ignore, sig); 2497*7c478bd9Sstevel@tonic-gate } 2498*7c478bd9Sstevel@tonic-gate bcopy(ip, &sqp->sq_info, sizeof (k_siginfo_t)); 2499*7c478bd9Sstevel@tonic-gate sigaddqa(p, curthread, sqp); 2500*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2501*7c478bd9Sstevel@tonic-gate } 2502*7c478bd9Sstevel@tonic-gate 2503*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 2504*7c478bd9Sstevel@tonic-gate 2505*7c478bd9Sstevel@tonic-gate /* 2506*7c478bd9Sstevel@tonic-gate * It's tricky to transmit a sigval between 32-bit and 64-bit 2507*7c478bd9Sstevel@tonic-gate * process, since in the 64-bit world, a pointer and an integer 2508*7c478bd9Sstevel@tonic-gate * are different sizes. Since we're constrained by the standards 2509*7c478bd9Sstevel@tonic-gate * world not to change the types, and it's unclear how useful it is 2510*7c478bd9Sstevel@tonic-gate * to send pointers between address spaces this way, we preserve 2511*7c478bd9Sstevel@tonic-gate * the 'int' interpretation for 32-bit processes interoperating 2512*7c478bd9Sstevel@tonic-gate * with 64-bit processes. The full semantics (pointers or integers) 2513*7c478bd9Sstevel@tonic-gate * are available for N-bit processes interoperating with N-bit 2514*7c478bd9Sstevel@tonic-gate * processes. 2515*7c478bd9Sstevel@tonic-gate */ 2516*7c478bd9Sstevel@tonic-gate void 2517*7c478bd9Sstevel@tonic-gate siginfo_kto32(const k_siginfo_t *src, siginfo32_t *dest) 2518*7c478bd9Sstevel@tonic-gate { 2519*7c478bd9Sstevel@tonic-gate bzero(dest, sizeof (*dest)); 2520*7c478bd9Sstevel@tonic-gate 2521*7c478bd9Sstevel@tonic-gate /* 2522*7c478bd9Sstevel@tonic-gate * The absolute minimum content is si_signo and si_code. 2523*7c478bd9Sstevel@tonic-gate */ 2524*7c478bd9Sstevel@tonic-gate dest->si_signo = src->si_signo; 2525*7c478bd9Sstevel@tonic-gate if ((dest->si_code = src->si_code) == SI_NOINFO) 2526*7c478bd9Sstevel@tonic-gate return; 2527*7c478bd9Sstevel@tonic-gate 2528*7c478bd9Sstevel@tonic-gate /* 2529*7c478bd9Sstevel@tonic-gate * A siginfo generated by user level is structured 2530*7c478bd9Sstevel@tonic-gate * differently from one generated by the kernel. 2531*7c478bd9Sstevel@tonic-gate */ 2532*7c478bd9Sstevel@tonic-gate if (SI_FROMUSER(src)) { 2533*7c478bd9Sstevel@tonic-gate dest->si_pid = src->si_pid; 2534*7c478bd9Sstevel@tonic-gate dest->si_ctid = src->si_ctid; 2535*7c478bd9Sstevel@tonic-gate dest->si_zoneid = src->si_zoneid; 2536*7c478bd9Sstevel@tonic-gate dest->si_uid = src->si_uid; 2537*7c478bd9Sstevel@tonic-gate if (SI_CANQUEUE(src->si_code)) 2538*7c478bd9Sstevel@tonic-gate dest->si_value.sival_int = 2539*7c478bd9Sstevel@tonic-gate (int32_t)src->si_value.sival_int; 2540*7c478bd9Sstevel@tonic-gate return; 2541*7c478bd9Sstevel@tonic-gate } 2542*7c478bd9Sstevel@tonic-gate 2543*7c478bd9Sstevel@tonic-gate dest->si_errno = src->si_errno; 2544*7c478bd9Sstevel@tonic-gate 2545*7c478bd9Sstevel@tonic-gate switch (src->si_signo) { 2546*7c478bd9Sstevel@tonic-gate default: 2547*7c478bd9Sstevel@tonic-gate dest->si_pid = src->si_pid; 2548*7c478bd9Sstevel@tonic-gate dest->si_ctid = src->si_ctid; 2549*7c478bd9Sstevel@tonic-gate dest->si_zoneid = src->si_zoneid; 2550*7c478bd9Sstevel@tonic-gate dest->si_uid = src->si_uid; 2551*7c478bd9Sstevel@tonic-gate dest->si_value.sival_int = (int32_t)src->si_value.sival_int; 2552*7c478bd9Sstevel@tonic-gate break; 2553*7c478bd9Sstevel@tonic-gate case SIGCLD: 2554*7c478bd9Sstevel@tonic-gate dest->si_pid = src->si_pid; 2555*7c478bd9Sstevel@tonic-gate dest->si_ctid = src->si_ctid; 2556*7c478bd9Sstevel@tonic-gate dest->si_zoneid = src->si_zoneid; 2557*7c478bd9Sstevel@tonic-gate dest->si_status = src->si_status; 2558*7c478bd9Sstevel@tonic-gate dest->si_stime = src->si_stime; 2559*7c478bd9Sstevel@tonic-gate dest->si_utime = src->si_utime; 2560*7c478bd9Sstevel@tonic-gate break; 2561*7c478bd9Sstevel@tonic-gate case SIGSEGV: 2562*7c478bd9Sstevel@tonic-gate case SIGBUS: 2563*7c478bd9Sstevel@tonic-gate case SIGILL: 2564*7c478bd9Sstevel@tonic-gate case SIGTRAP: 2565*7c478bd9Sstevel@tonic-gate case SIGFPE: 2566*7c478bd9Sstevel@tonic-gate case SIGEMT: 2567*7c478bd9Sstevel@tonic-gate dest->si_addr = (caddr32_t)(uintptr_t)src->si_addr; 2568*7c478bd9Sstevel@tonic-gate dest->si_trapno = src->si_trapno; 2569*7c478bd9Sstevel@tonic-gate dest->si_pc = (caddr32_t)(uintptr_t)src->si_pc; 2570*7c478bd9Sstevel@tonic-gate break; 2571*7c478bd9Sstevel@tonic-gate case SIGPOLL: 2572*7c478bd9Sstevel@tonic-gate case SIGXFSZ: 2573*7c478bd9Sstevel@tonic-gate dest->si_fd = src->si_fd; 2574*7c478bd9Sstevel@tonic-gate dest->si_band = src->si_band; 2575*7c478bd9Sstevel@tonic-gate break; 2576*7c478bd9Sstevel@tonic-gate case SIGPROF: 2577*7c478bd9Sstevel@tonic-gate dest->si_faddr = (caddr32_t)(uintptr_t)src->si_faddr; 2578*7c478bd9Sstevel@tonic-gate dest->si_tstamp.tv_sec = src->si_tstamp.tv_sec; 2579*7c478bd9Sstevel@tonic-gate dest->si_tstamp.tv_nsec = src->si_tstamp.tv_nsec; 2580*7c478bd9Sstevel@tonic-gate dest->si_syscall = src->si_syscall; 2581*7c478bd9Sstevel@tonic-gate dest->si_nsysarg = src->si_nsysarg; 2582*7c478bd9Sstevel@tonic-gate dest->si_fault = src->si_fault; 2583*7c478bd9Sstevel@tonic-gate break; 2584*7c478bd9Sstevel@tonic-gate } 2585*7c478bd9Sstevel@tonic-gate } 2586*7c478bd9Sstevel@tonic-gate 2587*7c478bd9Sstevel@tonic-gate void 2588*7c478bd9Sstevel@tonic-gate siginfo_32tok(const siginfo32_t *src, k_siginfo_t *dest) 2589*7c478bd9Sstevel@tonic-gate { 2590*7c478bd9Sstevel@tonic-gate bzero(dest, sizeof (*dest)); 2591*7c478bd9Sstevel@tonic-gate 2592*7c478bd9Sstevel@tonic-gate /* 2593*7c478bd9Sstevel@tonic-gate * The absolute minimum content is si_signo and si_code. 2594*7c478bd9Sstevel@tonic-gate */ 2595*7c478bd9Sstevel@tonic-gate dest->si_signo = src->si_signo; 2596*7c478bd9Sstevel@tonic-gate if ((dest->si_code = src->si_code) == SI_NOINFO) 2597*7c478bd9Sstevel@tonic-gate return; 2598*7c478bd9Sstevel@tonic-gate 2599*7c478bd9Sstevel@tonic-gate /* 2600*7c478bd9Sstevel@tonic-gate * A siginfo generated by user level is structured 2601*7c478bd9Sstevel@tonic-gate * differently from one generated by the kernel. 2602*7c478bd9Sstevel@tonic-gate */ 2603*7c478bd9Sstevel@tonic-gate if (SI_FROMUSER(src)) { 2604*7c478bd9Sstevel@tonic-gate dest->si_pid = src->si_pid; 2605*7c478bd9Sstevel@tonic-gate dest->si_ctid = src->si_ctid; 2606*7c478bd9Sstevel@tonic-gate dest->si_zoneid = src->si_zoneid; 2607*7c478bd9Sstevel@tonic-gate dest->si_uid = src->si_uid; 2608*7c478bd9Sstevel@tonic-gate if (SI_CANQUEUE(src->si_code)) 2609*7c478bd9Sstevel@tonic-gate dest->si_value.sival_int = 2610*7c478bd9Sstevel@tonic-gate (int)src->si_value.sival_int; 2611*7c478bd9Sstevel@tonic-gate return; 2612*7c478bd9Sstevel@tonic-gate } 2613*7c478bd9Sstevel@tonic-gate 2614*7c478bd9Sstevel@tonic-gate dest->si_errno = src->si_errno; 2615*7c478bd9Sstevel@tonic-gate 2616*7c478bd9Sstevel@tonic-gate switch (src->si_signo) { 2617*7c478bd9Sstevel@tonic-gate default: 2618*7c478bd9Sstevel@tonic-gate dest->si_pid = src->si_pid; 2619*7c478bd9Sstevel@tonic-gate dest->si_ctid = src->si_ctid; 2620*7c478bd9Sstevel@tonic-gate dest->si_zoneid = src->si_zoneid; 2621*7c478bd9Sstevel@tonic-gate dest->si_uid = src->si_uid; 2622*7c478bd9Sstevel@tonic-gate dest->si_value.sival_int = (int)src->si_value.sival_int; 2623*7c478bd9Sstevel@tonic-gate break; 2624*7c478bd9Sstevel@tonic-gate case SIGCLD: 2625*7c478bd9Sstevel@tonic-gate dest->si_pid = src->si_pid; 2626*7c478bd9Sstevel@tonic-gate dest->si_ctid = src->si_ctid; 2627*7c478bd9Sstevel@tonic-gate dest->si_zoneid = src->si_zoneid; 2628*7c478bd9Sstevel@tonic-gate dest->si_status = src->si_status; 2629*7c478bd9Sstevel@tonic-gate dest->si_stime = src->si_stime; 2630*7c478bd9Sstevel@tonic-gate dest->si_utime = src->si_utime; 2631*7c478bd9Sstevel@tonic-gate break; 2632*7c478bd9Sstevel@tonic-gate case SIGSEGV: 2633*7c478bd9Sstevel@tonic-gate case SIGBUS: 2634*7c478bd9Sstevel@tonic-gate case SIGILL: 2635*7c478bd9Sstevel@tonic-gate case SIGTRAP: 2636*7c478bd9Sstevel@tonic-gate case SIGFPE: 2637*7c478bd9Sstevel@tonic-gate case SIGEMT: 2638*7c478bd9Sstevel@tonic-gate dest->si_addr = (void *)(uintptr_t)src->si_addr; 2639*7c478bd9Sstevel@tonic-gate dest->si_trapno = src->si_trapno; 2640*7c478bd9Sstevel@tonic-gate dest->si_pc = (void *)(uintptr_t)src->si_pc; 2641*7c478bd9Sstevel@tonic-gate break; 2642*7c478bd9Sstevel@tonic-gate case SIGPOLL: 2643*7c478bd9Sstevel@tonic-gate case SIGXFSZ: 2644*7c478bd9Sstevel@tonic-gate dest->si_fd = src->si_fd; 2645*7c478bd9Sstevel@tonic-gate dest->si_band = src->si_band; 2646*7c478bd9Sstevel@tonic-gate break; 2647*7c478bd9Sstevel@tonic-gate case SIGPROF: 2648*7c478bd9Sstevel@tonic-gate dest->si_faddr = (void *)(uintptr_t)src->si_faddr; 2649*7c478bd9Sstevel@tonic-gate dest->si_tstamp.tv_sec = src->si_tstamp.tv_sec; 2650*7c478bd9Sstevel@tonic-gate dest->si_tstamp.tv_nsec = src->si_tstamp.tv_nsec; 2651*7c478bd9Sstevel@tonic-gate dest->si_syscall = src->si_syscall; 2652*7c478bd9Sstevel@tonic-gate dest->si_nsysarg = src->si_nsysarg; 2653*7c478bd9Sstevel@tonic-gate dest->si_fault = src->si_fault; 2654*7c478bd9Sstevel@tonic-gate break; 2655*7c478bd9Sstevel@tonic-gate } 2656*7c478bd9Sstevel@tonic-gate } 2657*7c478bd9Sstevel@tonic-gate 2658*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 2659