Annotation of XNU/bsd/kern/kern_sig.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* Copyright (c) 1995-1998 Apple Computer, Inc. All Rights Reserved */
        !            23: /*
        !            24:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
        !            25:  *     The Regents of the University of California.  All rights reserved.
        !            26:  * (c) UNIX System Laboratories, Inc.
        !            27:  * All or some portions of this file are derived from material licensed
        !            28:  * to the University of California by American Telephone and Telegraph
        !            29:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            30:  * the permission of UNIX System Laboratories, Inc.
        !            31:  *
        !            32:  * Redistribution and use in source and binary forms, with or without
        !            33:  * modification, are permitted provided that the following conditions
        !            34:  * are met:
        !            35:  * 1. Redistributions of source code must retain the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer.
        !            37:  * 2. Redistributions in binary form must reproduce the above copyright
        !            38:  *    notice, this list of conditions and the following disclaimer in the
        !            39:  *    documentation and/or other materials provided with the distribution.
        !            40:  * 3. All advertising materials mentioning features or use of this software
        !            41:  *    must display the following acknowledgement:
        !            42:  *     This product includes software developed by the University of
        !            43:  *     California, Berkeley and its contributors.
        !            44:  * 4. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)kern_sig.c  8.7 (Berkeley) 4/18/94
        !            61:  */
        !            62: 
        !            63: #define        SIGPROP         /* include signal properties table */
        !            64: #include <sys/param.h>
        !            65: #include <sys/signalvar.h>
        !            66: #include <sys/resourcevar.h>
        !            67: #include <sys/namei.h>
        !            68: #include <sys/vnode.h>
        !            69: #include <sys/proc.h>
        !            70: #include <sys/systm.h>
        !            71: #include <sys/timeb.h>
        !            72: #include <sys/times.h>
        !            73: #include <sys/buf.h>
        !            74: #include <sys/acct.h>
        !            75: #include <sys/file.h>
        !            76: #include <sys/kernel.h>
        !            77: #include <sys/wait.h>
        !            78: #include <sys/ktrace.h>
        !            79: #include <sys/syslog.h>
        !            80: #include <sys/stat.h>
        !            81: 
        !            82: #include <sys/mount.h>
        !            83: 
        !            84: #include <kern/cpu_number.h>
        !            85: 
        !            86: #include <sys/vm.h>
        !            87: #include <sys/user.h>          /* for coredump */
        !            88: #include <kern/ast.h>          /* for APC support */
        !            89: #include <kern/thread.h>
        !            90: 
        !            91: void stop __P((struct proc *p));
        !            92: int cansignal __P((struct proc *, struct pcred *, struct proc *, int));
        !            93: int killpg1 __P((struct proc *, int, int, int));
        !            94: void sigexit __P((struct proc *, int));
        !            95: void setsigvec __P((struct proc *, int, struct sigaction *));
        !            96: void exit1 __P((struct proc *, int));
        !            97: 
        !            98: /*
        !            99:  * Can process p, with pcred pc, send the signal signum to process q?
        !           100:  */
        !           101: int
        !           102: cansignal(p, pc, q, signum)
        !           103:        struct proc *p;
        !           104:        struct pcred *pc;
        !           105:        struct proc *q;
        !           106:        int signum;
        !           107: {
        !           108:        if (pc->pc_ucred->cr_uid == 0)
        !           109:                return (1);             /* root can always signal */
        !           110: 
        !           111:        if (signum == SIGCONT && q->p_session == p->p_session)
        !           112:                return (1);             /* SIGCONT in session */
        !           113: 
        !           114:        /*
        !           115:         * Using kill(), only certain signals can be sent to setugid
        !           116:         * child processes
        !           117:         */
        !           118:        if (q->p_flag & P_SUGID) {
        !           119:                switch (signum) {
        !           120:                case 0:
        !           121:                case SIGKILL:
        !           122:                case SIGINT:
        !           123:                case SIGTERM:
        !           124:                case SIGSTOP:
        !           125:                case SIGTTIN:
        !           126:                case SIGTTOU:
        !           127:                case SIGTSTP:
        !           128:                case SIGHUP:
        !           129:                case SIGUSR1:
        !           130:                case SIGUSR2:
        !           131:                        if (pc->p_ruid == q->p_cred->p_ruid ||
        !           132:                            pc->pc_ucred->cr_uid == q->p_cred->p_ruid ||
        !           133:                            pc->p_ruid == q->p_ucred->cr_uid ||
        !           134:                            pc->pc_ucred->cr_uid == q->p_ucred->cr_uid)
        !           135:                                return (1);
        !           136:                }
        !           137:                return (0);
        !           138:        }
        !           139: 
        !           140:        /* XXX
        !           141:         * because the P_SUGID test exists, this has extra tests which
        !           142:         * could be removed.
        !           143:         */
        !           144:        if (pc->p_ruid == q->p_cred->p_ruid ||
        !           145:            pc->p_ruid == q->p_cred->p_svuid ||
        !           146:            pc->pc_ucred->cr_uid == q->p_cred->p_ruid ||
        !           147:            pc->pc_ucred->cr_uid == q->p_cred->p_svuid ||
        !           148:            pc->p_ruid == q->p_ucred->cr_uid ||
        !           149:            pc->pc_ucred->cr_uid == q->p_ucred->cr_uid)
        !           150:                return (1);
        !           151:        return (0);
        !           152: }
        !           153: 
        !           154: struct sigaction_args {
        !           155:        int     signum;
        !           156:        struct sigaction *nsa;
        !           157:        struct sigaction *osa;
        !           158: };
        !           159: /* ARGSUSED */
        !           160: int
        !           161: sigaction(p, uap, retval)
        !           162:        struct proc *p;
        !           163:        register struct sigaction_args *uap;
        !           164:        register_t *retval;
        !           165: {
        !           166:        struct sigaction vec;
        !           167:        register struct sigaction *sa;
        !           168:        register struct sigacts *ps = p->p_sigacts;
        !           169:        register int signum;
        !           170:        int bit, error;
        !           171: 
        !           172:        signum = uap->signum;
        !           173:        if (signum <= 0 || signum >= NSIG ||
        !           174:            signum == SIGKILL || signum == SIGSTOP)
        !           175:                return (EINVAL);
        !           176:        sa = &vec;
        !           177:        if (uap->osa) {
        !           178:                sa->sa_handler = ps->ps_sigact[signum];
        !           179:                sa->sa_mask = ps->ps_catchmask[signum];
        !           180:                bit = sigmask(signum);
        !           181:                sa->sa_flags = 0;
        !           182:                if ((ps->ps_sigonstack & bit) != 0)
        !           183:                        sa->sa_flags |= SA_ONSTACK;
        !           184:                if ((ps->ps_sigintr & bit) == 0)
        !           185:                        sa->sa_flags |= SA_RESTART;
        !           186:                if (p->p_flag & P_NOCLDSTOP)
        !           187:                        sa->sa_flags |= SA_NOCLDSTOP;
        !           188:                if (error = copyout((caddr_t)sa, (caddr_t)uap->osa,
        !           189:                    sizeof (vec)))
        !           190:                        return (error);
        !           191:        }
        !           192:        if (uap->nsa) {
        !           193:                if (error = copyin((caddr_t)uap->nsa, (caddr_t)sa,
        !           194:                    sizeof (vec)))
        !           195:                        return (error);
        !           196:                setsigvec(p, signum, sa);
        !           197:        }
        !           198:        return (0);
        !           199: }
        !           200: bsd_resetbit(thread_act_t th_act, int bit) 
        !           201: {
        !           202: struct uthread *ut;
        !           203:        ut = get_bsdthread_info(th_act);
        !           204:        if (ut) {
        !           205:                ut->uu_sig &= ~bit;
        !           206:        }
        !           207: }
        !           208: 
        !           209: void
        !           210: setsigvec(p, signum, sa)
        !           211:        register struct proc *p;
        !           212:        int signum;
        !           213:        register struct sigaction *sa;
        !           214: {
        !           215:        register struct sigacts *ps = p->p_sigacts;
        !           216:        register int bit;
        !           217: 
        !           218:        bit = sigmask(signum);
        !           219:        /*
        !           220:         * Change setting atomically.
        !           221:         */
        !           222:        (void) splhigh();
        !           223:        simple_lock(&p->siglock);
        !           224:        ps->ps_sigact[signum] = sa->sa_handler;
        !           225:        ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask;
        !           226:        if ((sa->sa_flags & SA_RESTART) == 0)
        !           227:                ps->ps_sigintr |= bit;
        !           228:        else
        !           229:                ps->ps_sigintr &= ~bit;
        !           230:        if (sa->sa_flags & SA_ONSTACK)
        !           231:                ps->ps_sigonstack |= bit;
        !           232:        else
        !           233:                ps->ps_sigonstack &= ~bit;
        !           234:        if (sa->sa_flags & SA_USERTRAMP)
        !           235:                ps->ps_usertramp |= bit;
        !           236:        else
        !           237:                ps->ps_usertramp &= ~bit;
        !           238:        if (signum == SIGCHLD) {
        !           239:                if (sa->sa_flags & SA_NOCLDSTOP)
        !           240:                        p->p_flag |= P_NOCLDSTOP;
        !           241:                else
        !           242:                        p->p_flag &= ~P_NOCLDSTOP;
        !           243:        }
        !           244:        /*
        !           245:         * Set bit in p_sigignore for signals that are set to SIG_IGN,
        !           246:         * and for signals set to SIG_DFL where the default is to ignore.
        !           247:         * However, don't put SIGCONT in p_sigignore,
        !           248:         * as we have to restart the process.
        !           249:         */
        !           250:        if (sa->sa_handler == SIG_IGN ||
        !           251:            (sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) {
        !           252:                p->p_siglist &= ~bit;           /* never to be seen again */
        !           253:                /*
        !           254:                 *      If this is a thread signal, clean out the
        !           255:                 *      threads as well.
        !           256:                 */
        !           257:                if (bit & threadmask) {
        !           258:                        register        task_t          task = p->task;
        !           259: 
        !           260:                        task_act_iterate_wth_args(task, bsd_resetbit, bit);
        !           261:                }
        !           262:                if (signum != SIGCONT)
        !           263:                        p->p_sigignore |= bit;  /* easier in psignal */
        !           264:                p->p_sigcatch &= ~bit;
        !           265:        } else {
        !           266:                p->p_sigignore &= ~bit;
        !           267:                if (sa->sa_handler == SIG_DFL)
        !           268:                        p->p_sigcatch &= ~bit;
        !           269:                else
        !           270:                        p->p_sigcatch |= bit;
        !           271:        }
        !           272:        simple_unlock(&p->siglock);
        !           273:        (void) spl0();
        !           274: }
        !           275: 
        !           276: /*
        !           277:  * Initialize signal state for process 0;
        !           278:  * set to ignore signals that are ignored by default.
        !           279:  */
        !           280: void
        !           281: siginit(p)
        !           282:        struct proc *p;
        !           283: {
        !           284:        register int i;
        !           285: 
        !           286:        for (i = 0; i < NSIG; i++)
        !           287:                if (sigprop[i] & SA_IGNORE && i != SIGCONT)
        !           288:                        p->p_sigignore |= sigmask(i);
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * Reset signals for an exec of the specified process.
        !           293:  */
        !           294: void
        !           295: execsigs(p)
        !           296:        register struct proc *p;
        !           297: {
        !           298:        register struct sigacts *ps = p->p_sigacts;
        !           299:        register int nc, mask;
        !           300: 
        !           301:        /*
        !           302:         * Reset caught signals.  Held signals remain held
        !           303:         * through p_sigmask (unless they were caught,
        !           304:         * and are now ignored by default).
        !           305:         */
        !           306:        while (p->p_sigcatch) {
        !           307:                nc = ffs((long)p->p_sigcatch);
        !           308:                mask = sigmask(nc);
        !           309:                p->p_sigcatch &= ~mask;
        !           310:                if (sigprop[nc] & SA_IGNORE) {
        !           311:                        if (nc != SIGCONT)
        !           312:                                p->p_sigignore |= mask;
        !           313:                        p->p_siglist &= ~mask;
        !           314:                }
        !           315:                ps->ps_sigact[nc] = SIG_DFL;
        !           316:        }
        !           317:        /*
        !           318:         * Reset stack state to the user stack.
        !           319:         * Clear set of signals caught on the signal stack.
        !           320:         */
        !           321:        ps->ps_sigstk.ss_flags = SA_DISABLE;
        !           322:        ps->ps_sigstk.ss_size = 0;
        !           323:        ps->ps_sigstk.ss_sp = 0;
        !           324:        ps->ps_flags = 0;
        !           325: }
        !           326: 
        !           327: /*
        !           328:  * Manipulate signal mask.
        !           329:  * Note that we receive new mask, not pointer,
        !           330:  * and return old mask as return value;
        !           331:  * the library stub does the rest.
        !           332:  */
        !           333: struct sigprocmask_args {
        !           334:        int     how;
        !           335:        sigset_t mask;
        !           336: };
        !           337: int
        !           338: sigprocmask(p, uap, retval)
        !           339:        register struct proc *p;
        !           340:        struct sigprocmask_args *uap;
        !           341:        register_t *retval;
        !           342: {
        !           343:        int error = 0;
        !           344: 
        !           345:        *retval = p->p_sigmask;
        !           346:        (void) splhigh();
        !           347: 
        !           348:        switch (uap->how) {
        !           349:        case SIG_BLOCK:
        !           350:                p->p_sigmask |= uap->mask &~ sigcantmask;
        !           351:                break;
        !           352: 
        !           353:        case SIG_UNBLOCK:
        !           354:                p->p_sigmask &= ~(uap->mask);
        !           355: #ifdef BSD_USE_APC
        !           356:   thread_apc_set(current_act(), bsd_ast);
        !           357: #else
        !           358:                thread_ast_set(current_act(), AST_BSD);
        !           359:                ast_on(AST_BSD);  
        !           360: #endif
        !           361:                break;
        !           362: 
        !           363:        case SIG_SETMASK:
        !           364:                p->p_sigmask = uap->mask &~ sigcantmask;
        !           365: #ifdef BSD_USE_APC
        !           366:                thread_apc_set(current_act(), bsd_ast);
        !           367: #else
        !           368:                thread_ast_set(current_act(), AST_BSD);
        !           369:                ast_on(AST_BSD);
        !           370: #endif
        !           371:                break;
        !           372:        
        !           373:        default:
        !           374:                error = EINVAL;
        !           375:                break;
        !           376:        }
        !           377:        (void) spl0();
        !           378:        return (error);
        !           379: }
        !           380: 
        !           381: /* ARGSUSED */
        !           382: int
        !           383: sigpending(p, uap, retval)
        !           384:        struct proc *p;
        !           385:        void *uap;
        !           386:        register_t *retval;
        !           387: {
        !           388: 
        !           389:        *retval = p->p_siglist;
        !           390:        return (0);
        !           391: }
        !           392: 
        !           393: #if COMPAT_43
        !           394: /*
        !           395:  * Generalized interface signal handler, 4.3-compatible.
        !           396:  */
        !           397: struct osigvec_args {
        !           398:        int signum;
        !           399:        struct sigvec *nsv;
        !           400:        struct sigvec *osv;
        !           401: };
        !           402: /* ARGSUSED */
        !           403: int
        !           404: osigvec(p, uap, retval)
        !           405:        struct proc *p;
        !           406:        register struct osigvec_args *uap;
        !           407:        register_t *retval;
        !           408: {
        !           409:        struct sigvec vec;
        !           410:        register struct sigacts *ps = p->p_sigacts;
        !           411:        register struct sigvec *sv;
        !           412:        register int signum;
        !           413:        int bit, error;
        !           414: 
        !           415:        signum = uap->signum;
        !           416:        if (signum <= 0 || signum >= NSIG ||
        !           417:            signum == SIGKILL || signum == SIGSTOP)
        !           418:                return (EINVAL);
        !           419:        sv = &vec;
        !           420:        if (uap->osv) {
        !           421:                *(sig_t *)&sv->sv_handler = ps->ps_sigact[signum];
        !           422:                sv->sv_mask = ps->ps_catchmask[signum];
        !           423:                bit = sigmask(signum);
        !           424:                sv->sv_flags = 0;
        !           425:                if ((ps->ps_sigonstack & bit) != 0)
        !           426:                        sv->sv_flags |= SV_ONSTACK;
        !           427:                if ((ps->ps_sigintr & bit) != 0)
        !           428:                        sv->sv_flags |= SV_INTERRUPT;
        !           429:                        if (p->p_flag & P_NOCLDSTOP)
        !           430:                                sv->sv_flags |= SA_NOCLDSTOP;
        !           431:                if (error = copyout((caddr_t)sv, (caddr_t)uap->osv,
        !           432:                    sizeof (vec)))
        !           433:                        return (error);
        !           434:        }
        !           435:        if (uap->nsv) {
        !           436:                if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv,
        !           437:                    sizeof (vec)))
        !           438:                        return (error);
        !           439:                sv->sv_flags ^= SA_RESTART;     /* opposite of SV_INTERRUPT */
        !           440:                setsigvec(p, signum, (struct sigaction *)sv);
        !           441:        }
        !           442:        return (0);
        !           443: }
        !           444: 
        !           445: struct osigblock_args {
        !           446:        int mask;
        !           447: };
        !           448: int
        !           449: osigblock(p, uap, retval)
        !           450:        register struct proc *p;
        !           451:        struct osigblock_args *uap;
        !           452:        register_t *retval;
        !           453: {
        !           454: 
        !           455:        (void) splhigh();
        !           456:        *retval = p->p_sigmask;
        !           457:        p->p_sigmask |= uap->mask &~ sigcantmask;
        !           458:        (void) spl0();
        !           459:        return (0);
        !           460: }
        !           461: 
        !           462: struct osigsetmask_args {
        !           463:        int mask;
        !           464: };
        !           465: int
        !           466: osigsetmask(p, uap, retval)
        !           467:        struct proc *p;
        !           468:        struct osigsetmask_args *uap;
        !           469:        register_t *retval;
        !           470: {
        !           471: 
        !           472:        (void) splhigh();
        !           473:        *retval = p->p_sigmask;
        !           474:        p->p_sigmask = uap->mask &~ sigcantmask;
        !           475:        (void) spl0();
        !           476:        return (0);
        !           477: }
        !           478: #endif /* COMPAT_43 */
        !           479: 
        !           480: /*
        !           481:  * Suspend process until signal, providing mask to be set
        !           482:  * in the meantime.  Note nonstandard calling convention:
        !           483:  * libc stub passes mask, not pointer, to save a copyin.
        !           484:  */
        !           485: 
        !           486: int
        !           487: sigcontinue(error)
        !           488: {
        !           489:   unix_syscall_return(EINTR);
        !           490: }
        !           491: 
        !           492: struct sigsuspend_args {
        !           493:        int mask;
        !           494: };
        !           495: /* ARGSUSED */
        !           496: int
        !           497: sigsuspend(p, uap, retval)
        !           498:        register struct proc *p;
        !           499:        struct sigsuspend_args *uap;
        !           500:        register_t *retval;
        !           501: {
        !           502:        register struct sigacts *ps = p->p_sigacts;
        !           503: 
        !           504:        /*
        !           505:         * When returning from sigpause, we want
        !           506:         * the old mask to be restored after the
        !           507:         * signal handler has finished.  Thus, we
        !           508:         * save it here and mark the sigacts structure
        !           509:         * to indicate this.
        !           510:         */
        !           511:        ps->ps_oldmask = p->p_sigmask;
        !           512:        ps->ps_flags |= SAS_OLDMASK;
        !           513:        p->p_sigmask = uap->mask &~ sigcantmask;
        !           514:        (void) tsleep0((caddr_t) p, PPAUSE|PCATCH, "pause", 0, sigcontinue);
        !           515:        /* always return EINTR rather than ERESTART... */
        !           516:        return (EINTR);
        !           517: }
        !           518: 
        !           519: #if COMPAT_43
        !           520: struct osigstack_args {
        !           521:        struct sigstack *nss;
        !           522:        struct sigstack *oss;
        !           523: };
        !           524: /* ARGSUSED */
        !           525: int
        !           526: osigstack(p, uap, retval)
        !           527:        struct proc *p;
        !           528:        register struct osigstack_args *uap;
        !           529:        register_t *retval;
        !           530: {
        !           531:        struct sigstack ss;
        !           532:        struct sigacts *psp;
        !           533:        int error = 0;
        !           534: 
        !           535:        psp = p->p_sigacts;
        !           536:        ss.ss_sp = psp->ps_sigstk.ss_sp;
        !           537:        ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
        !           538:        if (uap->oss && (error = copyout((caddr_t)&ss,
        !           539:            (caddr_t)uap->oss, sizeof (struct sigstack))))
        !           540:                return (error);
        !           541:        if (uap->nss && (error = copyin((caddr_t)uap->nss,
        !           542:            (caddr_t)&ss, sizeof (ss))) == 0) {
        !           543:                psp->ps_sigstk.ss_sp = ss.ss_sp;
        !           544:                psp->ps_sigstk.ss_size = 0;
        !           545:                psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK;
        !           546:                psp->ps_flags |= SAS_ALTSTACK;
        !           547:        }
        !           548:        return (error);
        !           549: }
        !           550: #endif /* COMPAT_43 */
        !           551: 
        !           552: struct sigaltstack_args {
        !           553:        struct sigaltstack *nss;
        !           554:        struct sigaltstack *oss;
        !           555: };
        !           556: /* ARGSUSED */
        !           557: int
        !           558: sigaltstack(p, uap, retval)
        !           559:        struct proc *p;
        !           560:        register struct sigaltstack_args *uap;
        !           561:        register_t *retval;
        !           562: {
        !           563:        struct sigacts *psp;
        !           564:        struct sigaltstack ss;
        !           565:        int error;
        !           566: 
        !           567:        psp = p->p_sigacts;
        !           568:        if ((psp->ps_flags & SAS_ALTSTACK) == 0)
        !           569:                psp->ps_sigstk.ss_flags |= SA_DISABLE;
        !           570:        if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk,
        !           571:            (caddr_t)uap->oss, sizeof (struct sigaltstack))))
        !           572:                return (error);
        !           573:        if (uap->nss == 0)
        !           574:                return (0);
        !           575:        if (error = copyin((caddr_t)uap->nss, (caddr_t)&ss,
        !           576:            sizeof (ss)))
        !           577:                return (error);
        !           578:        if (ss.ss_flags & SA_DISABLE) {
        !           579:                if (psp->ps_sigstk.ss_flags & SA_ONSTACK)
        !           580:                        return (EINVAL);
        !           581:                psp->ps_flags &= ~SAS_ALTSTACK;
        !           582:                psp->ps_sigstk.ss_flags = ss.ss_flags;
        !           583:                return (0);
        !           584:        }
        !           585:        if (ss.ss_size < MINSIGSTKSZ)
        !           586:                return (ENOMEM);
        !           587:        psp->ps_flags |= SAS_ALTSTACK;
        !           588:        psp->ps_sigstk= ss;
        !           589:        return (0);
        !           590: }
        !           591: 
        !           592: struct kill_args {
        !           593:        int pid;
        !           594:        int signum;
        !           595: };
        !           596: /* ARGSUSED */
        !           597: int
        !           598: kill(cp, uap, retval)
        !           599:        register struct proc *cp;
        !           600:        register struct kill_args *uap;
        !           601:        register_t *retval;
        !           602: {
        !           603:        register struct proc *p;
        !           604:        register struct pcred *pc = cp->p_cred;
        !           605: 
        !           606:        if ((u_int)uap->signum >= NSIG)
        !           607:                return (EINVAL);
        !           608:        if (uap->pid > 0) {
        !           609:                /* kill single process */
        !           610:                if ((p = pfind(uap->pid)) == NULL)
        !           611:                        return (ESRCH);
        !           612:                if (!cansignal(cp, pc, p, uap->signum))
        !           613:                        return (EPERM);
        !           614:                if (uap->signum)
        !           615:                        psignal(p, uap->signum);
        !           616:                return (0);
        !           617:        }
        !           618:        switch (uap->pid) {
        !           619:        case -1:                /* broadcast signal */
        !           620:                return (killpg1(cp, uap->signum, 0, 1));
        !           621:        case 0:                 /* signal own process group */
        !           622:                return (killpg1(cp, uap->signum, 0, 0));
        !           623:        default:                /* negative explicit process group */
        !           624:                return (killpg1(cp, uap->signum, -(uap->pid), 0));
        !           625:        }
        !           626:        /* NOTREACHED */
        !           627: }
        !           628: 
        !           629: #if COMPAT_43
        !           630: struct okillpg_args {
        !           631:        int pgid;
        !           632:        int signum;
        !           633: };
        !           634: /* ARGSUSED */
        !           635: int
        !           636: okillpg(p, uap, retval)
        !           637:        struct proc *p;
        !           638:        register struct okillpg_args *uap;
        !           639:        register_t *retval;
        !           640: {
        !           641: 
        !           642:        if ((u_int)uap->signum >= NSIG)
        !           643:                return (EINVAL);
        !           644:        return (killpg1(p, uap->signum, uap->pgid, 0));
        !           645: }
        !           646: #endif /* COMPAT_43 */
        !           647: 
        !           648: /*
        !           649:  * Common code for kill process group/broadcast kill.
        !           650:  * cp is calling process.
        !           651:  */
        !           652: int
        !           653: killpg1(cp, signum, pgid, all)
        !           654:        register struct proc *cp;
        !           655:        int signum, pgid, all;
        !           656: {
        !           657:        register struct proc *p;
        !           658:        register struct pcred *pc = cp->p_cred;
        !           659:        struct pgrp *pgrp;
        !           660:        int nfound = 0;
        !           661:        
        !           662:        if (all)        
        !           663:                /* 
        !           664:                 * broadcast 
        !           665:                 */
        !           666:                for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
        !           667:                        if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || 
        !           668:                            p == cp || !cansignal(cp, pc, p, signum))
        !           669:                                continue;
        !           670:                        nfound++;
        !           671:                        if (signum)
        !           672:                                psignal(p, signum);
        !           673:                }
        !           674:        else {
        !           675:                if (pgid == 0)          
        !           676:                        /* 
        !           677:                         * zero pgid means send to my process group.
        !           678:                         */
        !           679:                        pgrp = cp->p_pgrp;
        !           680:                else {
        !           681:                        pgrp = pgfind(pgid);
        !           682:                        if (pgrp == NULL)
        !           683:                                return (ESRCH);
        !           684:                }
        !           685:                for (p = pgrp->pg_members.lh_first; p != 0;
        !           686:                     p = p->p_pglist.le_next) {
        !           687:                        if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
        !           688:                            p->p_stat == SZOMB ||
        !           689:                            !cansignal(cp, pc, p, signum))
        !           690:                                continue;
        !           691:                        nfound++;
        !           692:                        if (signum)
        !           693:                                psignal(p, signum);
        !           694:                }
        !           695:        }
        !           696:        return (nfound ? 0 : ESRCH);
        !           697: }
        !           698: 
        !           699: /*
        !           700:  * Send a signal to a process group.
        !           701:  */
        !           702: void
        !           703: gsignal(pgid, signum)
        !           704:        int pgid, signum;
        !           705: {
        !           706:        struct pgrp *pgrp;
        !           707: 
        !           708:        if (pgid && (pgrp = pgfind(pgid)))
        !           709:                pgsignal(pgrp, signum, 0);
        !           710: }
        !           711: 
        !           712: /*
        !           713:  * Send a signal to a process group.  If checktty is 1,
        !           714:  * limit to members which have a controlling terminal.
        !           715:  */
        !           716: void
        !           717: pgsignal(pgrp, signum, checkctty)
        !           718:        struct pgrp *pgrp;
        !           719:        int signum, checkctty;
        !           720: {
        !           721:        register struct proc *p;
        !           722: 
        !           723:        if (pgrp)
        !           724:                for (p = pgrp->pg_members.lh_first; p != 0;
        !           725:                     p = p->p_pglist.le_next)
        !           726:                        if (checkctty == 0 || p->p_flag & P_CONTROLT)
        !           727:                                psignal(p, signum);
        !           728: }
        !           729: 
        !           730: /*
        !           731:  * Send a signal caused by a trap to a specific thread.
        !           732:  */
        !           733: void
        !           734: threadsignal(sig_actthread, signum, code)
        !           735:        register thread_act_t *sig_actthread;
        !           736:        register int signum;
        !           737:        u_long code;
        !           738: {
        !           739:        register struct uthread *uth;
        !           740:        register struct task * sig_task;
        !           741:        register struct proc *p ;
        !           742:        int mask;
        !           743: 
        !           744:        if ((u_int)signum >= NSIG || signum == 0)
        !           745:                return;
        !           746: 
        !           747:        mask = sigmask(signum);
        !           748:        if ((mask & threadmask) == 0)
        !           749:                return;
        !           750:        sig_task = get_threadtask(sig_actthread);
        !           751:        /* p = sig_task->proc; */
        !           752:        p = (struct proc *)(get_bsdtask_info(sig_task));
        !           753: 
        !           754:        if (!(p->p_flag & P_TRACED) && (p->p_sigignore & mask))
        !           755:                return;
        !           756: 
        !           757:        uth = get_bsdthread_info(sig_actthread);
        !           758:        simple_lock(&p->siglock);
        !           759:        uth->uu_sig |= mask;
        !           760:        uth->uu_code = code;
        !           761: #ifdef BSD_USE_APC
        !           762:  thread_apc_set(sig_actthread, bsd_ast);
        !           763: #else
        !           764:        thread_ast_set(sig_actthread,AST_BSD);
        !           765:  if (current_act() == sig_actthread)
        !           766:      ast_on(AST_BSD);
        !           767: #endif   
        !           768:        simple_unlock(&p->siglock);
        !           769: }
        !           770: 
        !           771: /*
        !           772:  * Send the signal to the process.  If the signal has an action, the action
        !           773:  * is usually performed by the target process rather than the caller; we add
        !           774:  * the signal to the set of pending signals for the process.
        !           775:  *
        !           776:  * Exceptions:
        !           777:  *   o When a stop signal is sent to a sleeping process that takes the
        !           778:  *     default action, the process is stopped without awakening it.
        !           779:  *   o SIGCONT restarts stopped processes (or puts them back to sleep)
        !           780:  *     regardless of the signal action (eg, blocked or ignored).
        !           781:  *
        !           782:  * Other ignored signals are discarded immediately.
        !           783:  */
        !           784: void
        !           785: psignal(p, signum)
        !           786:        register struct proc *p;
        !           787:        register int signum;
        !           788: {
        !           789:        register int s, prop;
        !           790:        register sig_t action;
        !           791:        register thread_act_t   sig_thread_act;
        !           792:        register thread_t       sig_thread;
        !           793:        register task_t         sig_task;
        !           794:        register thread_t       cur_thread;
        !           795:        thread_act_t    *cur_act;
        !           796:        int mask;
        !           797: 
        !           798:        if ((u_int)signum >= NSIG || signum == 0)
        !           799:                panic("psignal signal number");
        !           800:        mask = sigmask(signum);
        !           801:        prop = sigprop[signum];
        !           802: 
        !           803:        /*
        !           804:         *      We will need the task pointer later.  Grab it now to
        !           805:         *      check for a zombie process.  Also don't send signals
        !           806:         *      to kernel internal tasks.
        !           807:         */
        !           808:        if (((sig_task = p->task) == TASK_NULL)  || is_kerneltask(sig_task))
        !           809:                return;
        !           810: 
        !           811:        /*
        !           812:         * If proc is traced, always give parent a chance.
        !           813:         */
        !           814:        if (p->p_flag & P_TRACED)
        !           815:                action = SIG_DFL;
        !           816:        else {
        !           817:                /*
        !           818:                 * If the signal is being ignored,
        !           819:                 * then we forget about it immediately.
        !           820:                 * (Note: we don't set SIGCONT in p_sigignore,
        !           821:                 * and if it is set to SIG_IGN,
        !           822:                 * action will be SIG_DFL here.)
        !           823:                 */
        !           824:                if (p->p_sigignore & mask)
        !           825:                        return;
        !           826:                if (p->p_sigmask & mask)
        !           827:                        action = SIG_HOLD;
        !           828:                else if (p->p_sigcatch & mask)
        !           829:                        action = SIG_CATCH;
        !           830:                else
        !           831:                        action = SIG_DFL;
        !           832:        }
        !           833: 
        !           834:        if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) &&
        !           835:                (p->p_flag & P_TRACED) == 0)
        !           836:                p->p_nice = NZERO;
        !           837: 
        !           838:        if (prop & SA_CONT)
        !           839:                p->p_siglist &= ~stopsigmask;
        !           840: 
        !           841:        if (prop & SA_STOP) {
        !           842:                /*
        !           843:                 * If sending a tty stop signal to a member of an orphaned
        !           844:                 * process group, discard the signal here if the action
        !           845:                 * is default; don't stop the process below if sleeping,
        !           846:                 * and don't clear any pending SIGCONT.
        !           847:                 */
        !           848:                if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 &&
        !           849:                    action == SIG_DFL)
        !           850:                        return;
        !           851:                p->p_siglist &= ~contsigmask;
        !           852:        }
        !           853:        p->p_siglist |= mask;
        !           854: 
        !           855:        /*
        !           856:         * Defer further processing for signals which are held,
        !           857:         * except that stopped processes must be continued by SIGCONT.
        !           858:         */
        !           859:        if (action == SIG_HOLD && ((prop & SA_CONT) == 0 || p->p_stat != SSTOP))
        !           860:                return;
        !           861:                
        !           862:        /*
        !           863:         *      Deliver the signal to the first thread in the task. This
        !           864:         *      allows single threaded applications which use signals to
        !           865:         *      be able to be linked with multithreaded libraries.  We have
        !           866:         *      an implicit reference to the current_thread, but need
        !           867:         *      an explicit one otherwise.  The thread reference keeps
        !           868:         *      the corresponding task data structures around too.  This
        !           869:         *      reference is released by thread_deallocate.
        !           870:         */
        !           871:        
        !           872:        s = splhigh();
        !           873:        cur_thread = current_thread();   /* this is a shuttle */
        !           874:        cur_act = current_act();
        !           875:        
        !           876:        task_tllock(sig_task);
        !           877:        sig_thread_act = (thread_t) get_firstthread(sig_task);
        !           878:        
        !           879:        if (sig_thread_act == THREAD_NULL) {
        !           880:                task_tlunlock(sig_task);
        !           881:                (void) splx(s);
        !           882:                return;
        !           883:        }
        !           884:        sig_thread = getshuttle_thread(sig_thread_act);
        !           885:        if (sig_thread == THREAD_NULL) {
        !           886:                printf("WARNING: valid act; but no shutte in psignal\n");
        !           887: #if 0
        !           888:                /* FIXME : NO VALID SHUTTLE */
        !           889:                task_tlunlock(sig_task);
        !           890:                (void) splx(s);
        !           891:                return;
        !           892: #endif
        !           893:        }
        !           894: #ifdef BSD_USE_APC
        !           895:        thread_apc_set(sig_thread_act, bsd_ast);
        !           896: #else
        !           897:        thread_ast_set(sig_thread_act,AST_BSD);
        !           898:        if (cur_act == sig_thread_act)
        !           899:            ast_on(AST_BSD); 
        !           900: #endif  
        !           901: 
        !           902: /* #if FIXME */
        !           903:        if (sig_thread != cur_thread)
        !           904:                act_reference(sig_thread_act);
        !           905: /* #endif */
        !           906:        task_tlunlock(sig_task);
        !           907: 
        !           908:        /*
        !           909:         *      SIGKILL priority twiddling moved here from above because
        !           910:         *      it needs sig_thread.  Could merge it into large switch
        !           911:         *      below if we didn't care about priority for tracing
        !           912:         *      as SIGKILL's action is always SIG_DFL.
        !           913:         */
        !           914:        if ((signum == SIGKILL) && (p->p_nice > NZERO)) {
        !           915:                p->p_nice = NZERO;
        !           916: #if FIXME  /* [ */
        !           917:                thread_max_priority(sig_thread, sig_thread->processor_set,
        !           918:                        BASEPRI_USER);
        !           919:                thread_priority(sig_thread, BASEPRI_USER, FALSE);
        !           920: #endif  /* FIXME ] */
        !           921:        }
        !           922: 
        !           923:        /*
        !           924:         *      Process is traced - wake it up (if not already
        !           925:         *      stopped) so that it can discover the signal in
        !           926:         *      issig() and stop for the parent.
        !           927:         */
        !           928:        if (p->p_flag & P_TRACED) {
        !           929:                if (p->p_stat != SSTOP)
        !           930:                        goto run;
        !           931:                else
        !           932:                        goto out;
        !           933:        }
        !           934: 
        !           935:        if (action != SIG_DFL) {
        !           936:                /*
        !           937:                 *      User wants to catch the signal.
        !           938:                 *      Wake up the thread, but don't un-suspend it
        !           939:                 *      (except for SIGCONT).
        !           940:                 */
        !           941:                if (prop & SA_CONT)
        !           942:                        (void) task_resume(sig_task);
        !           943:                goto run;
        !           944:        } else {
        !           945:                /*      Default action - varies */
        !           946: 
        !           947:                if (mask & stopsigmask) {
        !           948:                        /*
        !           949:                         * These are the signals which by default
        !           950:                         * stop a process.
        !           951:                         *
        !           952:                         * Don't clog system with children of init
        !           953:                         * stopped from the keyboard.
        !           954:                         */
        !           955:                        if (!(prop & SA_STOP) && p->p_pptr == initproc) {
        !           956:                                psignal(p, SIGKILL);
        !           957:                                p->p_siglist &= ~mask;
        !           958:                                goto out;
        !           959:                        }
        !           960:                        /*
        !           961:                         *      Stop the task.
        !           962:                         */
        !           963:                        if (!is_thread_running(sig_thread)) {
        !           964:                                /*  Thread is not running 
        !           965:                                 *      If task hasn't already been stopped by
        !           966:                                 *      a signal, stop it.
        !           967:                                 */
        !           968:                                p->p_siglist &= ~mask;
        !           969:                                if (get_task_userstop(sig_task) == 0) {
        !           970:                                        /*
        !           971:                                         * p_cursig must not be set, because
        !           972:                                         * it will be psig()'d if it is not
        !           973:                                         * zero, and the signal is being
        !           974:                                         * handled here.  But save the signal
        !           975:                                         * in p_stopsig so WUNTRACED
        !           976:                                         * option to wait can find it.
        !           977:                                         */
        !           978:                                        p->p_xstat = signum;
        !           979:                                        if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)
        !           980:                                                psignal(p->p_pptr, SIGCHLD);
        !           981:                                        stop(p);
        !           982:                                }
        !           983:                                goto out;
        !           984:          } else {                      
        !           985:     if ((p == current_proc()) && (p->p_stat != SZOMB)) {
        !           986: 
        !           987: #ifdef BSD_USE_APC
        !           988:                                        thread_apc_set(cur_act, bsd_ast);
        !           989: #else
        !           990:                                        thread_ast_set(cur_act, AST_BSD);
        !           991:                                        ast_on(AST_BSD);
        !           992: #endif
        !           993: 
        !           994:                                }
        !           995:                                goto out;
        !           996:                        }
        !           997:                }
        !           998: 
        !           999:                switch (signum) {
        !          1000:                        /*
        !          1001:                         * Signals ignored by default have been dealt
        !          1002:                         * with already, since their bits are on in
        !          1003:                         * p_sigignore.
        !          1004:                         */
        !          1005: 
        !          1006:                case SIGKILL:
        !          1007:                        /*
        !          1008:                         * Kill signal always sets process running and
        !          1009:                         * unsuspends it.
        !          1010:                         */
        !          1011:                        while (get_task_userstop(sig_task) > 0)
        !          1012:                                (void) task_resume(sig_task);
        !          1013:                        /*
        !          1014:                         *      Process will be running after 'run'
        !          1015:                         */
        !          1016:                        p->p_stat = SRUN;
        !          1017: 
        !          1018:                        /*
        !          1019:                         * Break it out of user wait, as well.
        !          1020:                         */
        !          1021:                        while (get_thread_userstop(sig_thread_act) > 0)
        !          1022:                                (void) thread_resume(sig_thread_act);
        !          1023: 
        !          1024:                        /*
        !          1025:                         * Clear system wait if possible.
        !          1026:                         */
        !          1027:                        clear_wait(sig_thread, THREAD_INTERRUPTED, FALSE);
        !          1028: #if    MACH_HOST
        !          1029:                        /*
        !          1030:                         * Make sure it can run.
        !          1031:                         */
        !          1032:                        if (sig_thread->processor_set->empty)
        !          1033:                                thread_assign(sig_thread, &default_pset);
        !          1034: #endif
        !          1035:                        /*
        !          1036:                         * If we're delivering the signal to some other
        !          1037:                         * thread, that thread might be stuck in an
        !          1038:                         * exception.  Break it out.  Can't call
        !          1039:                         * thread_exception_abort from high spl, but
        !          1040:                         * SIGKILL can't be sent from interrupt level, so
        !          1041:                         * it's ok to drop spl.  Can call thread_deallocate
        !          1042:                         * for same reason.
        !          1043:                         */
        !          1044:                        splx(s);
        !          1045:                        if (sig_thread != cur_thread) {
        !          1046:                                thread_abort(sig_thread_act);
        !          1047: /* #if FIXME */
        !          1048:                                act_deallocate(sig_thread_act);
        !          1049: /* #endif  */
        !          1050:                        }
        !          1051:                        return;
        !          1052: 
        !          1053:                case SIGCONT:
        !          1054:                        /*
        !          1055:                         * Let the process run.  If it's sleeping on an
        !          1056:                         * event, it remains so.
        !          1057:                         */
        !          1058:                        (void) task_resume(sig_task);
        !          1059:                        p->p_stat = SRUN;
        !          1060:                        goto out;
        !          1061: 
        !          1062:                default:
        !          1063:                        /*
        !          1064:                         * All other signals wake up the process, but don't
        !          1065:                         * resume it.
        !          1066:                         */
        !          1067:                        goto run;
        !          1068:                }
        !          1069:        }
        !          1070:        /*NOTREACHED*/
        !          1071: run:
        !          1072:        /*
        !          1073:         * If we're being traced (possibly because someone attached us
        !          1074:         * while we were stopped), check for a signal from the debugger.
        !          1075:         */
        !          1076:     if (p->p_stat == SSTOP) {
        !          1077:         if ((p->p_flag & P_TRACED) != 0 && p->p_xstat != 0)
        !          1078:             p->p_siglist |= sigmask(p->p_xstat); 
        !          1079:     }
        !          1080: 
        !          1081:        /*
        !          1082:         * setrunnable(p) in BSD
        !          1083:         */
        !          1084: 
        !          1085:        p->p_stat = SRUN;
        !          1086: 
        !          1087:        /*
        !          1088:         *      Wake up the thread if it is interruptible.
        !          1089:         */
        !          1090:        clear_wait(sig_thread, THREAD_INTERRUPTED, TRUE);
        !          1091: out:
        !          1092:        splx(s);
        !          1093:        /*** FIXME revisit this->who calls up ipc_thread_deallocate?? ***/
        !          1094:        if (sig_thread != cur_thread)
        !          1095:                act_deallocate(sig_thread_act);
        !          1096: }
        !          1097: 
        !          1098: __inline__ void
        !          1099: sig_lock_to_exit(
        !          1100:        struct proc     *p)
        !          1101: {
        !          1102:        thread_t        self = current_thread();
        !          1103: 
        !          1104:        p->exit_thread = self;
        !          1105:        simple_unlock(&p->siglock);
        !          1106:        (void) task_hold(p->task);
        !          1107:        (void) task_dowait(p->task, FALSE);
        !          1108: }
        !          1109: 
        !          1110: __inline__ int
        !          1111: sig_try_lock(
        !          1112:        struct proc     *p)
        !          1113: {
        !          1114:        thread_t        self = current_thread();
        !          1115: 
        !          1116:        simple_lock(&p->siglock);
        !          1117:        while (p->sigwait || p->exit_thread) {
        !          1118:                 simple_unlock(&p->siglock);
        !          1119:                 if (p->exit_thread) {
        !          1120:                        if (p->exit_thread == self) {
        !          1121:                                /*
        !          1122:                                 * Already exiting - no signals.
        !          1123:                                 */
        !          1124:                                return 0;
        !          1125:                        }
        !          1126:                        else {
        !          1127:                                /*
        !          1128:                                 * Another thread has called exit -
        !          1129:                                 * stop (until terminate request).
        !          1130:                                 */
        !          1131:                                thread_hold(current_act());
        !          1132:                        }
        !          1133:                }
        !          1134:                if(assert_wait_possible()) {
        !          1135:                        assert_wait((caddr_t)&p->sigwait_thread, THREAD_UNINT);
        !          1136:                }
        !          1137:                thread_block(0);
        !          1138:                if (thread_should_abort(self)) {
        !          1139:                        /*
        !          1140:                         * Terminate request - clean up.
        !          1141:                         */
        !          1142:                        return -1;
        !          1143:                }
        !          1144:                simple_lock(&p->siglock);
        !          1145:        }
        !          1146: 
        !          1147:        return 1;
        !          1148: }
        !          1149: 
        !          1150: /*
        !          1151:  * If the current process has received a signal (should be caught or cause
        !          1152:  * termination, should interrupt current syscall), return the signal number.
        !          1153:  * Stop signals with default action are processed immediately, then cleared;
        !          1154:  * they aren't returned.  This is checked after each entry to the system for
        !          1155:  * a syscall or trap (though this can usually be done without calling issignal
        !          1156:  * by checking the pending signal masks in the CURSIG macro.) The normal call
        !          1157:  * sequence is
        !          1158:  *
        !          1159:  *     while (signum = CURSIG(curproc))
        !          1160:  *             postsig(signum);
        !          1161:  */
        !          1162: int
        !          1163: issignal(p)
        !          1164:        register struct proc *p;
        !          1165: {
        !          1166:        register int signum, mask, prop, sigbits;
        !          1167:        task_t task = p->task;
        !          1168:        thread_act_t initial_threadact;
        !          1169:        thread_t cur_thread;
        !          1170:        thread_act_t cur_act;
        !          1171:        int     s;
        !          1172:        struct uthread * ut;
        !          1173: 
        !          1174: #if DIAGNOSTIC
        !          1175:        /*
        !          1176:         *      This must be called on master cpu
        !          1177:         */
        !          1178:        if (cpu_number() != master_cpu)
        !          1179:                panic("issig not on master");
        !          1180: #endif /* DIAGNOSTIC */
        !          1181: 
        !          1182:        /*
        !          1183:         * Try to grab the signal lock.
        !          1184:         */
        !          1185:        if (sig_try_lock(p) <= 0)
        !          1186:                return (0);
        !          1187:        
        !          1188:        /*
        !          1189:         * only allow delivery of process signals (asynchronous)
        !          1190:         * to the initial thread. This is the first thread in
        !          1191:         * the tasks thread list.
        !          1192:         */
        !          1193:        initial_threadact = (thread_t)get_firstthread(task);
        !          1194:        cur_thread = current_thread();
        !          1195:        cur_act = current_act();
        !          1196: 
        !          1197:        
        !          1198:                ut = get_bsdthread_info(cur_act);
        !          1199:        for(;;) {
        !          1200:                sigbits = (ut->uu_sig |p->p_siglist) & ~p->p_sigmask;
        !          1201: 
        !          1202:                for (;;) {
        !          1203:                        if (p->p_flag & P_PPWAIT)
        !          1204:                                sigbits &= ~stopsigmask;
        !          1205:                        if (sigbits == 0) {             /* no signal to send */
        !          1206:                                simple_unlock(&p->siglock);
        !          1207:                                return (0);
        !          1208:                        }
        !          1209:                        signum = ffs((long)sigbits);
        !          1210:                        mask = sigmask(signum);
        !          1211:                        prop = sigprop[signum];
        !          1212:                
        !          1213:                        if (mask & threadmask) {
        !          1214:                                /* we can take this signal */
        !          1215:                                ut->uu_sig &= ~mask;
        !          1216:                                break;
        !          1217:                        } else {
        !          1218:                                if (cur_act != initial_threadact)
        !          1219:                                                sigbits &= ~mask;
        !          1220:                                else
        !          1221:                                        break;
        !          1222:                                }
        !          1223:                }
        !          1224: 
        !          1225:                        
        !          1226:                /*
        !          1227:                 * We should see pending but ignored signals
        !          1228:                 * only if P_TRACED was on when they were posted.
        !          1229:                 */
        !          1230:                if (mask & p->p_sigignore && (p->p_flag & P_TRACED) == 0) {
        !          1231:                        p->p_siglist &= ~mask;          /* take the signal! */
        !          1232:                        continue;
        !          1233:                }
        !          1234:                if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
        !          1235:                        register int    hold;
        !          1236:                        register task_t task;
        !          1237:                        /*
        !          1238:                         * If traced, always stop, and stay
        !          1239:                         * stopped until released by the debugger.
        !          1240:                         */
        !          1241: 
        !          1242:                        if (p->p_flag & P_FSTRACE) {
        !          1243: #if    PROCFS
        !          1244:                                /* procfs debugging */
        !          1245:                                p->p_stat = SSTOP;
        !          1246:                                wakeup((caddr_t)p);
        !          1247: #error need to implement 
        !          1248:                                panic("procfs debugging");
        !          1249: #endif
        !          1250:                        } else {
        !          1251: #ifndef _WANT_GDB_TO_PANIC_
        !          1252:                               /*
        !          1253:                                * We may have already been assert_waited as
        !          1254:                                * part of a sleep, but we are going to
        !          1255:                                * subvert what we are sleeping on here.
        !          1256:                                * Since task_hold()/task_dowait() can
        !          1257:                                * block themselves, clear out the old
        !          1258:                                * condition here.
        !          1259:                                */
        !          1260:                               clear_wait(cur_thread, THREAD_INTERRUPTED, FALSE);
        !          1261: #endif /* !_WANT_GDB_TO_PANIC_ */                              
        !          1262: 
        !          1263:                                /* ptrace debugging */
        !          1264:                                p->p_xstat = signum;
        !          1265:                                psignal(p->p_pptr, SIGCHLD);
        !          1266:                                pcb_synch(cur_thread);
        !          1267:                                /*
        !          1268:                                 *      XXX Have to really stop for debuggers;
        !          1269:                                 *      XXX stop() doesn't do the right thing.
        !          1270:                                 *      XXX Inline the task_suspend because we
        !          1271:                                 *      XXX have to diddle Unix state in the
        !          1272:                                 *      XXX middle of it.
        !          1273:                                 */
        !          1274:                                task = p->task;
        !          1275:                                hold = FALSE;
        !          1276:                                if (inc_task_userstop(task) == 0)
        !          1277:                                        hold = TRUE;
        !          1278:                                if (hold) {
        !          1279:                                        (void) task_hold(task);
        !          1280:                                        act_reference(cur_act);
        !          1281:                                        p->sigwait = TRUE;
        !          1282:                                        p->sigwait_thread = cur_act;
        !          1283:                                        simple_unlock(&p->siglock);
        !          1284:                                        (void) task_dowait(task, TRUE);
        !          1285:                                }
        !          1286:                                else {
        !          1287:                                        act_reference(cur_act);
        !          1288:                                        p->sigwait = TRUE;
        !          1289:                                        p->sigwait_thread = cur_act;
        !          1290:                                        simple_unlock(&p->siglock);
        !          1291:                                }
        !          1292:                                p->p_stat = SSTOP;
        !          1293:                                p->p_flag &= ~P_WAITED;
        !          1294:                                p->p_siglist &= ~mask;  /* clear the old signal */
        !          1295: 
        !          1296:                                wakeup((caddr_t)p->p_pptr);
        !          1297:                                assert_wait((caddr_t)&p->sigwait, THREAD_UNINT);
        !          1298:                                thread_block(0);
        !          1299:                                simple_lock(&p->siglock);
        !          1300:                                p->sigwait = FALSE;
        !          1301:                                p->sigwait_thread = NULL;
        !          1302:                                wakeup((caddr_t)&p->sigwait_thread);
        !          1303:                                act_deallocate(cur_act);
        !          1304: 
        !          1305:                        /*
        !          1306:                         *      We get here only if task
        !          1307:                         *      is continued or killed.  Kill condition
        !          1308:                         *      is signalled by adding NSIG to p_cursig.
        !          1309:                         *      Pass original p_cursig as exit value in
        !          1310:                         *      this case.
        !          1311:                         */
        !          1312:                        if (p->p_siglist & sigmask(SIGKILL)) {
        !          1313:                                /*
        !          1314:                                 *      Wait event may still be outstanding;
        !          1315:                                 *      clear it, since sig_lock_to_exit will
        !          1316:                                 *      wait.
        !          1317:                                 */
        !          1318:                                clear_wait(current_thread(),
        !          1319:                                        THREAD_INTERRUPTED,
        !          1320:                                        FALSE);
        !          1321:                                sig_lock_to_exit(p);
        !          1322:                                /*
        !          1323:                                 * Since this thread will be resumed
        !          1324:                                 * to allow the current syscall to
        !          1325:                                 * be completed, must save u_qsave
        !          1326:                                 * before calling exit().  (Since exit()
        !          1327:                                 * calls closef() which can trash u_qsave.)
        !          1328:                                 */
        !          1329:                                exit1(p,signum);
        !          1330:                        }
        !          1331: 
        !          1332:                                /*
        !          1333:                                 *      We may have to quit
        !          1334:                                 */
        !          1335:                                if (thread_should_abort(current_thread())) {
        !          1336:                                        simple_unlock(&p->siglock);
        !          1337:                                        return(0);
        !          1338:                                }
        !          1339: 
        !          1340:                                /*
        !          1341:                                 * If the traced bit got turned off, go back up
        !          1342:                                 * to the top to rescan signals.  This ensures
        !          1343:                                 * that p_sig* and ps_sigact are consistent.
        !          1344:                                 */
        !          1345:                                if ((p->p_flag & P_TRACED) == 0) {
        !          1346:                                        if (mask & threadmask)
        !          1347:                                                ut->uu_sig |= mask;
        !          1348:                                        else
        !          1349:                                                p->p_siglist |= mask;
        !          1350:                                        continue;
        !          1351:                                }
        !          1352: 
        !          1353:                                /*
        !          1354:                                * If parent wants us to take the signal,
        !          1355:                                * then it will leave it in p->p_xstat;
        !          1356:                                * otherwise we just look for signals again.
        !          1357:                                */
        !          1358:                                signum = p->p_xstat;
        !          1359:                                if (signum == 0)
        !          1360:                                        continue;
        !          1361:                                /*
        !          1362:                                 * Put the new signal into p_siglist.  If the
        !          1363:                                 * signal is being masked, look for other signals.
        !          1364:                                 */
        !          1365:                                mask = sigmask(signum);
        !          1366:                                if (mask & threadmask)
        !          1367:                                        ut->uu_sig |= mask;
        !          1368:                                else
        !          1369:                                        p->p_siglist |= mask;
        !          1370:                                if (p->p_sigmask & mask)
        !          1371:                                        continue;
        !          1372:                        }
        !          1373:                }
        !          1374: 
        !          1375:                /*
        !          1376:                 * Decide whether the signal should be returned.
        !          1377:                 * Return the signal's number, or fall through
        !          1378:                 * to clear it from the pending mask.
        !          1379:                 */
        !          1380: 
        !          1381:                switch ((long)p->p_sigacts->ps_sigact[signum]) {
        !          1382:                
        !          1383:                case (long)SIG_DFL:
        !          1384:                        /*
        !          1385:                         * Don't take default actions on system processes.
        !          1386:                         */
        !          1387:                        if (p->p_pptr->p_pid == 0) {
        !          1388: #if DIAGNOSTIC
        !          1389:                                /*
        !          1390:                                 * Are you sure you want to ignore SIGSEGV
        !          1391:                                 * in init? XXX
        !          1392:                                 */
        !          1393:                                printf("Process (pid %d) got signal %d\n",
        !          1394:                                        p->p_pid, signum);
        !          1395: #endif
        !          1396:                                break;                          /* == ignore */
        !          1397:                        }
        !          1398:                        
        !          1399:                        /*
        !          1400:                         * If there is a pending stop signal to process
        !          1401:                         * with default action, stop here,
        !          1402:                         * then clear the signal.  However,
        !          1403:                         * if process is member of an orphaned
        !          1404:                         * process group, ignore tty stop signals.
        !          1405:                         */
        !          1406:                        if (prop & SA_STOP) {
        !          1407:                                if (p->p_flag & P_TRACED ||
        !          1408:                                    (p->p_pgrp->pg_jobc == 0 &&
        !          1409:                                    prop & SA_TTYSTOP))
        !          1410:                                        break;  /* == ignore */
        !          1411:                                p->p_xstat = signum;
        !          1412:                                stop(p);
        !          1413:                                if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)
        !          1414:                                        psignal(p->p_pptr, SIGCHLD);
        !          1415:                                act_reference(cur_act);
        !          1416:                                p->sigwait = TRUE;
        !          1417:                                p->sigwait_thread = cur_act;
        !          1418:                                simple_unlock(&p->siglock);
        !          1419:                                thread_block(0);
        !          1420:                                simple_lock(&p->siglock);
        !          1421:                                p->sigwait = FALSE;
        !          1422:                                p->sigwait_thread = NULL;
        !          1423:                                wakeup((caddr_t)&p->sigwait_thread);
        !          1424:                                act_deallocate(cur_act);
        !          1425:                                /*
        !          1426:                                 *      We may have to quit
        !          1427:                                 */
        !          1428:                                if (thread_should_abort(current_thread())) {
        !          1429:                                        simple_unlock(&p->siglock);
        !          1430:                                        return(0);
        !          1431:                                }
        !          1432:                                break;
        !          1433:                        } else if (prop & SA_IGNORE) {
        !          1434:                                /*
        !          1435:                                 * Except for SIGCONT, shouldn't get here.
        !          1436:                                 * Default action is to ignore; drop it.
        !          1437:                                 */
        !          1438:                                break;          /* == ignore */
        !          1439:                        } else {
        !          1440:                                simple_unlock(&p->siglock);
        !          1441:                                return (signum);
        !          1442:                        }
        !          1443:                        /*NOTREACHED*/
        !          1444: 
        !          1445:                case (long)SIG_IGN:
        !          1446:                        /*
        !          1447:                         * Masking above should prevent us ever trying
        !          1448:                         * to take action on an ignored signal other
        !          1449:                         * than SIGCONT, unless process is traced.
        !          1450:                         */
        !          1451:                        if ((prop & SA_CONT) == 0 &&
        !          1452:                            (p->p_flag & P_TRACED) == 0)
        !          1453:                                printf("issignal\n");
        !          1454:                        break;          /* == ignore */
        !          1455: 
        !          1456:                default:
        !          1457:                        /*
        !          1458:                         * This signal has an action, let
        !          1459:                         * postsig() process it.
        !          1460:                         */
        !          1461:                        simple_unlock(&p->siglock);
        !          1462:                        return (signum);
        !          1463:                }
        !          1464:                p->p_siglist &= ~mask;          /* take the signal! */
        !          1465:                }
        !          1466:        /* NOTREACHED */
        !          1467: }
        !          1468: 
        !          1469: /*
        !          1470:  * Put the argument process into the stopped state and notify the parent
        !          1471:  * via wakeup.  Signals are handled elsewhere.  The process must not be
        !          1472:  * on the run queue.
        !          1473:  */
        !          1474: void
        !          1475: stop(p)
        !          1476:        register struct proc *p;
        !          1477: {
        !          1478: 
        !          1479:        /*
        !          1480:         *      Call special task_suspend routine,
        !          1481:         *      because this routine is called from interrupts
        !          1482:         *      (psignal) and cannot sleep.
        !          1483:         */
        !          1484: #ifdef FIXME
        !          1485:        /* not clear why moving thread suspend matters*/
        !          1486:        (void) task_suspend_nowait(p->task);    /*XXX*/
        !          1487: 
        !          1488:        p->p_stat = SSTOP;
        !          1489:        p->p_flag &= ~P_WAITED;
        !          1490:        wakeup((caddr_t)p->p_pptr);
        !          1491: #else
        !          1492: 
        !          1493:        p->p_stat = SSTOP;
        !          1494:        p->p_flag &= ~P_WAITED;
        !          1495:        wakeup((caddr_t)p->p_pptr);
        !          1496:        (void) task_suspend_nowait(p->task);    /*XXX*/
        !          1497: 
        !          1498: #endif /* FIXME */
        !          1499: }
        !          1500: 
        !          1501: /*
        !          1502:  * Take the action for the specified signal
        !          1503:  * from the current set of pending signals.
        !          1504:  */
        !          1505: void
        !          1506: postsig(signum)
        !          1507:        register int signum;
        !          1508: {
        !          1509:        register struct proc *p = current_proc();
        !          1510:        register struct sigacts *ps = p->p_sigacts;
        !          1511:        register sig_t action;
        !          1512:        u_long code;
        !          1513:        int mask, returnmask;
        !          1514: 
        !          1515: #if DIAGNOSTIC
        !          1516:        if (signum == 0)
        !          1517:                panic("postsig");
        !          1518:        /*
        !          1519:         *      This must be called on master cpu
        !          1520:         */
        !          1521:        if (cpu_number() != master_cpu)
        !          1522:                panic("psig not on master");
        !          1523: #endif
        !          1524: 
        !          1525:        /*
        !          1526:         * Try to grab the signal lock.
        !          1527:         */
        !          1528:        if (sig_try_lock(p) <= 0)
        !          1529:                return;
        !          1530: 
        !          1531:        mask = sigmask(signum);
        !          1532:        p->p_siglist &= ~mask;
        !          1533:        action = ps->ps_sigact[signum];
        !          1534: #if KTRACE
        !          1535:        if (KTRPOINT(p, KTR_PSIG))
        !          1536:                ktrpsig(p->p_tracep,
        !          1537:                    signum, action, ps->ps_flags & SAS_OLDMASK ?
        !          1538:                    ps->ps_oldmask : p->p_sigmask, 0);
        !          1539: #endif
        !          1540:        if (action == SIG_DFL) {
        !          1541:                /*
        !          1542:                 * Default action, where the default is to kill
        !          1543:                 * the process.  (Other cases were ignored above.)
        !          1544:                 */
        !          1545:                 /* called with sig_lock() held */
        !          1546:                sigexit(p, signum);
        !          1547:                /* NOTREACHED */
        !          1548:        } else {
        !          1549:                /*
        !          1550:                 * If we get here, the signal must be caught.
        !          1551:                 */
        !          1552: #if DIAGNOSTIC
        !          1553:                if (action == SIG_IGN || (p->p_sigmask & mask))
        !          1554:                    log(LOG_WARNING,
        !          1555:                        "postsig: processing masked or ignored signal\n");
        !          1556: #endif
        !          1557:                /*
        !          1558:                 * Set the new mask value and also defer further
        !          1559:                 * occurences of this signal.
        !          1560:                 *
        !          1561:                 * Special case: user has done a sigpause.  Here the
        !          1562:                 * current mask is not of interest, but rather the
        !          1563:                 * mask from before the sigpause is what we want
        !          1564:                 * restored after the signal processing is completed.
        !          1565:                 */
        !          1566:                (void) splhigh();
        !          1567:                if (ps->ps_flags & SAS_OLDMASK) {
        !          1568:                        returnmask = ps->ps_oldmask;
        !          1569:                        ps->ps_flags &= ~SAS_OLDMASK;
        !          1570:                } else
        !          1571:                        returnmask = p->p_sigmask;
        !          1572:                p->p_sigmask |= ps->ps_catchmask[signum] | mask;
        !          1573:                if (ps->ps_sig != signum) {
        !          1574:                        code = 0;
        !          1575:                } else {
        !          1576:                        code = ps->ps_code;
        !          1577:                        ps->ps_code = 0;
        !          1578:                }
        !          1579:                simple_unlock(&p->siglock);
        !          1580:                (void) spl0();
        !          1581:                p->p_stats->p_ru.ru_nsignals++;
        !          1582:                sendsig(p, action, signum, returnmask, code);
        !          1583:        }
        !          1584: }
        !          1585: 
        !          1586: /*
        !          1587:  * Force the current process to exit with the specified signal, dumping core
        !          1588:  * if appropriate.  We bypass the normal tests for masked and caught signals,
        !          1589:  * allowing unrecoverable failures to terminate the process without changing
        !          1590:  * signal state.  Mark the accounting record with the signal termination.
        !          1591:  * If dumping core, save the signal number for the debugger.  Calls exit and
        !          1592:  * does not return.
        !          1593:  */
        !          1594: void
        !          1595: sigexit(p, signum)
        !          1596:        register struct proc *p;
        !          1597:        int signum;
        !          1598: {
        !          1599: 
        !          1600:        sig_lock_to_exit(p);
        !          1601:        p->p_acflag |= AXSIG;
        !          1602:        if (sigprop[signum] & SA_CORE) {
        !          1603:                p->p_sigacts->ps_sig = signum;
        !          1604:                if (coredump(p) == 0)
        !          1605:                        signum |= WCOREFLAG;
        !          1606:        }
        !          1607:        exit1(p, W_EXITCODE(0, signum));
        !          1608:        /* NOTREACHED */
        !          1609: }
        !          1610: 
        !          1611: void
        !          1612: bsd_ast(thread_act_t thr_act)
        !          1613: {       
        !          1614:        struct proc *p = current_proc();
        !          1615:        struct uthread *ut = get_bsdthread_info(thr_act);
        !          1616:        int     signum;
        !          1617:        unsigned int pc;
        !          1618:        boolean_t funnel_state;
        !          1619: 
        !          1620:        if (p == NULL)
        !          1621:                return;
        !          1622: 
        !          1623:        funnel_state = thread_set_funneled(TRUE);
        !          1624: 
        !          1625:        if ((p->p_flag & P_OWEUPC) && (p->p_flag & P_PROFIL)) {
        !          1626:                pc = get_useraddr();
        !          1627:                addupc_task(p, pc, 1);
        !          1628:                p->p_flag &= ~P_OWEUPC;
        !          1629:        }
        !          1630: 
        !          1631:        if (CHECK_SIGNALS(p, current_thread(), ut)) {
        !          1632:                while (signum = issignal(p))
        !          1633:                        postsig(signum);
        !          1634:        }
        !          1635: #ifdef BSD_USE_APC
        !          1636:        thread_apc_clear(thr_act, bsd_ast);
        !          1637: #else
        !          1638:        ast_off(AST_BSD);
        !          1639: #endif
        !          1640: 
        !          1641:        (void) thread_set_funneled(funnel_state);
        !          1642: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.