X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..c18c124eaa464aaaa5549e99e5a70fc9cbb50944:/bsd/kern/kern_sig.c diff --git a/bsd/kern/kern_sig.c b/bsd/kern/kern_sig.c index de5455812..bb44111fe 100644 --- a/bsd/kern/kern_sig.c +++ b/bsd/kern/kern_sig.c @@ -101,7 +101,6 @@ #include #include /* for coredump */ #include /* for APC support */ -#include #include /* extern void *get_bsdtask_info(task_t); */ #include #include @@ -121,8 +120,9 @@ extern int thread_enable_fpe(thread_t act, int onoff); extern thread_t port_name_to_thread(mach_port_name_t port_name); extern kern_return_t get_signalact(task_t , thread_t *, int); -extern boolean_t thread_should_abort(thread_t); extern unsigned int get_useraddr(void); +extern kern_return_t task_suspend_internal(task_t); +extern kern_return_t task_resume_internal(task_t); /* * --- @@ -655,7 +655,7 @@ siginit(proc_t p) { int i; - for (i = 0; i < NSIG; i++) + for (i = 1; i < NSIG; i++) if (sigprop[i] & SA_IGNORE && i != SIGCONT) p->p_sigignore |= sigmask(i); } @@ -1637,7 +1637,7 @@ threadsignal(thread_t sig_actthread, int signum, mach_exception_code_t code) p = (proc_t)(get_bsdtask_info(sig_task)); uth = get_bsdthread_info(sig_actthread); - if (uth && (uth->uu_flag & UT_VFORK)) + if (uth->uu_flag & UT_VFORK) p = uth->uu_proc; proc_lock(p); @@ -1711,7 +1711,7 @@ static void psignal_internal(proc_t p, task_t task, thread_t thread, int flavor, int signum) { int prop; - sig_t action = NULL; + user_addr_t action = USER_ADDR_NULL; proc_t sig_proc; thread_t sig_thread; register task_t sig_task; @@ -1936,7 +1936,7 @@ psignal_internal(proc_t p, task_t task, thread_t thread, int flavor, int signum) sig_proc->p_contproc = current_proc()->p_pid; proc_unlock(sig_proc); - (void) task_resume(sig_task); + (void) task_resume_internal(sig_task); goto psigout; } proc_unlock(sig_proc); @@ -1952,7 +1952,7 @@ psignal_internal(proc_t p, task_t task, thread_t thread, int flavor, int signum) if (prop & SA_CONT) { OSBitOrAtomic(P_CONTINUED, &sig_proc->p_flag); proc_unlock(sig_proc); - (void) task_resume(sig_task); + (void) task_resume_internal(sig_task); proc_lock(sig_proc); sig_proc->p_stat = SRUN; } else if (sig_proc->p_stat == SSTOP) { @@ -2069,7 +2069,6 @@ psignal_internal(proc_t p, task_t task, thread_t thread, int flavor, int signum) * Process will be running after 'run' */ sig_proc->p_stat = SRUN; - proc_unlock(sig_proc); /* * In scenarios where suspend/resume are racing * the signal we are missing AST_BSD by the time @@ -2079,6 +2078,7 @@ psignal_internal(proc_t p, task_t task, thread_t thread, int flavor, int signum) */ act_set_astbsd(sig_thread); thread_abort(sig_thread); + proc_unlock(sig_proc); goto psigout; @@ -2091,7 +2091,7 @@ psignal_internal(proc_t p, task_t task, thread_t thread, int flavor, int signum) sig_proc->p_contproc = sig_proc->p_pid; proc_unlock(sig_proc); - (void) task_resume(sig_task); + (void) task_resume_internal(sig_task); proc_lock(sig_proc); /* * When processing a SIGCONT, we need to check @@ -2206,7 +2206,7 @@ psignal_uthread(thread_t thread, int signum) * postsig(signum); */ int -issignal(proc_t p) +issignal_locked(proc_t p) { int signum, mask, prop, sigbits; thread_t cur_act; @@ -2223,13 +2223,11 @@ issignal(proc_t p) ram_printf(3); } #endif /* SIGNAL_DEBUG */ - proc_lock(p); /* * Try to grab the signal lock. */ if (sig_try_locked(p) <= 0) { - proc_unlock(p); return(0); } @@ -2300,12 +2298,9 @@ issignal(proc_t p) /* * XXX Have to really stop for debuggers; * XXX stop() doesn't do the right thing. - * XXX Inline the task_suspend because we - * XXX have to diddle Unix state in the - * XXX middle of it. */ task = p->task; - task_suspend(task); + task_suspend_internal(task); proc_lock(p); p->sigwait = TRUE; @@ -2362,6 +2357,7 @@ issignal(proc_t p) KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_FRCEXIT) | DBG_FUNC_NONE, p->p_pid, W_EXITCODE(0, SIGKILL), 2, 0, 0); exit1(p, W_EXITCODE(0, SIGKILL), (int *)NULL); + proc_lock(p); return(0); } @@ -2503,7 +2499,6 @@ issignal(proc_t p) /* NOTREACHED */ out: proc_signalend(p, 1); - proc_unlock(p); return(retval); } @@ -2645,7 +2640,7 @@ stop(proc_t p, proc_t parent) wakeup((caddr_t)parent); proc_list_unlock(); } - (void) task_suspend(p->task); /*XXX*/ + (void) task_suspend_internal(p->task); } /* @@ -2653,7 +2648,7 @@ stop(proc_t p, proc_t parent) * from the current set of pending signals. */ void -postsig(int signum) +postsig_locked(int signum) { proc_t p = current_proc(); struct sigacts *ps = p->p_sigacts; @@ -2672,12 +2667,10 @@ postsig(int signum) panic("psig not on master"); #endif - proc_lock(p); /* * Try to grab the signal lock. */ if (sig_try_locked(p) <= 0) { - proc_unlock(p); return; } @@ -2698,7 +2691,7 @@ postsig(int signum) p->p_sigacts->ps_sig = signum; proc_signalend(p, 1); proc_unlock(p); - if (coredump(p) == 0) + if (coredump(p, 0, 0) == 0) signum |= WCOREFLAG; } else { proc_signalend(p, 1); @@ -2713,6 +2706,16 @@ postsig(int signum) ut->t_dtrace_siginfo.si_uid = p->si_uid; ut->t_dtrace_siginfo.si_status = WEXITSTATUS(p->si_status); + /* Fire DTrace proc:::fault probe when signal is generated by hardware. */ + switch (signum) { + case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP: + DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo)); + break; + default: + break; + } + + DTRACE_PROC3(signal__handle, int, signum, siginfo_t *, &(ut->t_dtrace_siginfo), void (*)(void), SIG_DFL); #endif @@ -2720,6 +2723,7 @@ postsig(int signum) KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_FRCEXIT) | DBG_FUNC_NONE, p->p_pid, W_EXITCODE(0, signum), 3, 0, 0); exit1(p, W_EXITCODE(0, signum), (int *)NULL); + proc_lock(p); return; } else { /* @@ -2767,7 +2771,6 @@ postsig(int signum) sendsig(p, catcher, signum, returnmask, code); } proc_signalend(p, 1); - proc_unlock(p); } /* @@ -2940,7 +2943,7 @@ bsd_ast(thread_t thread) proc_lock(p); p->p_dtrace_stop = 1; proc_unlock(p); - (void)task_suspend(p->task); + (void)task_suspend_internal(p->task); } if (ut->t_dtrace_resumepid) { @@ -2952,7 +2955,7 @@ bsd_ast(thread_t thread) if (resumeproc->p_dtrace_stop) { resumeproc->p_dtrace_stop = 0; proc_unlock(resumeproc); - task_resume(resumeproc->task); + task_resume_internal(resumeproc->task); } else { proc_unlock(resumeproc); @@ -2963,10 +2966,12 @@ bsd_ast(thread_t thread) #endif /* CONFIG_DTRACE */ + proc_lock(p); if (CHECK_SIGNALS(p, current_thread(), ut)) { - while ( (signum = issignal(p)) ) - postsig(signum); + while ( (signum = issignal_locked(p)) ) + postsig_locked(signum); } + proc_unlock(p); if (!bsd_init_done) { bsd_init_done = 1; @@ -3083,6 +3088,10 @@ proc_signalstart(proc_t p, int locked) { if (!locked) proc_lock(p); + + if(p->p_signalholder == current_thread()) + panic("proc_signalstart: thread attempting to signal a process for which it holds the signal lock"); + p->p_sigwaitcnt++; while ((p->p_lflag & P_LINSIGNAL) == P_LINSIGNAL) msleep(&p->p_sigmask, &p->p_mlock, 0, "proc_signstart", NULL); @@ -3116,7 +3125,10 @@ sig_lock_to_exit(proc_t p) p->exit_thread = self; proc_unlock(p); - (void) task_suspend(p->task); + + task_hold(p->task); + task_wait(p->task, FALSE); + proc_lock(p); }