-
- default:
- /*
- * All other signals wake up the process, but don't
- * resume it.
- */
- if (p->p_stat == SSTOP)
- goto psigout;
- goto run;
- }
- }
- /*NOTREACHED*/
-run:
- /*
- * If we're being traced (possibly because someone attached us
- * while we were stopped), check for a signal from the debugger.
- */
- if (p->p_stat == SSTOP) {
- if ((p->p_flag & P_TRACED) != 0 && p->p_xstat != 0)
- uth->uu_siglist |= sigmask(p->p_xstat);
- } else {
- /*
- * setrunnable(p) in BSD and
- * Wake up the thread if it is interruptible.
- */
- p->p_stat = SRUN;
- thread_abort_safely(sig_thread_act);
- }
-psigout:
- if (withlock)
- signal_unlock(p);
- if (sw_funnel)
- thread_funnel_set(kernel_flock, funnel_state);
-}
-
-
-/* psignal_lock(p, signum, withlock ) */
-void
-psignal_uthread(thr_act, signum)
- thread_t thr_act;
- int signum;
-{
- struct proc *p;
- register int prop;
- register sig_t action;
- thread_t sig_thread_act;
- register task_t sig_task;
- int mask;
- struct uthread *uth;
- kern_return_t kret;
- int error = 0;
-
- p = (struct proc *)get_bsdtask_info(get_threadtask(thr_act));
- if ((u_int)signum >= NSIG || signum == 0)
- panic("Invalid signal number in psignal_uthread");
- mask = sigmask(signum);
- prop = sigprop[signum];
-
-#if SIGNAL_DEBUG
- if(rdebug_proc && (p == rdebug_proc)) {
- ram_printf(3);
- }
-#endif /* SIGNAL_DEBUG */
-
- /*
- * We will need the task pointer later. Grab it now to
- * check for a zombie process. Also don't send signals
- * to kernel internal tasks.
- */
- if (((sig_task = p->task) == TASK_NULL) || is_kerneltask(sig_task)) {
- return;
- }
-
- sig_thread_act = thr_act;
- /*
- * do not send signals to the process that has the thread
- * doing a reboot(). Not doing so will mark that thread aborted
- * and can cause IO failures wich will cause data loss.
- */
- if (ISSET(p->p_flag, P_REBOOT)) {
- return;
- }
-
- signal_lock(p);
-
- /*
- * Deliver the signal to the first thread in the task. This
- * allows single threaded applications which use signals to
- * be able to be linked with multithreaded libraries. We have
- * an implicit reference to the current thread, but need
- * an explicit one otherwise. The thread reference keeps
- * the corresponding task data structures around too. This
- * reference is released by thread_deallocate.
- */
-
- if (((p->p_flag & P_TRACED) == 0) && (p->p_sigignore & mask))
- goto puthout;
-
- kret = check_actforsig(sig_task, sig_thread_act, 1);
-
- if (kret != KERN_SUCCESS) {
- error = EINVAL;
- goto puthout;
- }
-
-
- uth = get_bsdthread_info(sig_thread_act);
-
- /*
- * If proc is traced, always give parent a chance.
- */
- if (p->p_flag & P_TRACED)
- action = SIG_DFL;
- else {
- /*
- * If the signal is being ignored,
- * then we forget about it immediately.
- * (Note: we don't set SIGCONT in p_sigignore,
- * and if it is set to SIG_IGN,
- * action will be SIG_DFL here.)
- */
- if (p->p_sigignore & mask)
- goto puthout;
- /* sigwait takes precedence */
- if (uth->uu_sigwait & mask)
- action = KERN_SIG_WAIT;
- else if (uth->uu_sigmask & mask)
- action = KERN_SIG_HOLD;
- else if (p->p_sigcatch & mask)
- action = KERN_SIG_CATCH;
- else
- action = SIG_DFL;
- }
-
- if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) &&
- (p->p_flag & P_TRACED) == 0)
- p->p_nice = NZERO;
-
- if (prop & SA_CONT) {
- uth->uu_siglist &= ~stopsigmask;
- p->p_siglist &= ~stopsigmask;
- }
-
- if (prop & SA_STOP) {
- /*
- * If sending a tty stop signal to a member of an orphaned
- * process group, discard the signal here if the action
- * is default; don't stop the process below if sleeping,
- * and don't clear any pending SIGCONT.
- */
- if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 &&
- action == SIG_DFL)
- goto puthout;
- uth->uu_siglist &= ~contsigmask;
- p->p_siglist &= ~contsigmask;
- }
- uth->uu_siglist |= mask;
- p->p_siglist |= mask; /* just for lame ones looking here */
-
- /*
- * Defer further processing for signals which are held,
- * except that stopped processes must be continued by SIGCONT.
- */
- if (action == KERN_SIG_HOLD && ((prop & SA_CONT) == 0 || p->p_stat != SSTOP))
- goto puthout;
-
- /*
- * SIGKILL priority twiddling moved here from above because
- * it needs sig_thread. Could merge it into large switch
- * below if we didn't care about priority for tracing
- * as SIGKILL's action is always SIG_DFL.
- */
- if ((signum == SIGKILL) && (p->p_nice > NZERO)) {
- p->p_nice = NZERO;
- }
-
- /*
- * Process is traced - wake it up (if not already
- * stopped) so that it can discover the signal in
- * issig() and stop for the parent.
- */
- if (p->p_flag & P_TRACED) {
- if (p->p_stat != SSTOP)
- goto psurun;
- else
- goto puthout;
- }
-
- if (action == KERN_SIG_WAIT) {
- uth->uu_sigwait = mask;
- uth->uu_siglist &= ~mask;
- p->p_siglist &= ~mask;
- wakeup(&uth->uu_sigwait);
- /* if it is SIGCONT resume whole process */
- if (prop & SA_CONT) {
- p->p_flag |= P_CONTINUED;
- (void) task_resume(sig_task);