]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sig.c
xnu-2782.20.48.tar.gz
[apple/xnu.git] / bsd / kern / kern_sig.c
index de545581243a15a8a2510f4ea7bb439a6df28cab..bb44111fe96b4f051793d3502dcd884f4bacf6f0 100644 (file)
 #include <sys/vm.h>
 #include <sys/user.h>          /* for coredump */
 #include <kern/ast.h>          /* for APC support */
-#include <kern/lock.h>
 #include <kern/task.h>         /* extern void   *get_bsdtask_info(task_t); */
 #include <kern/thread.h>
 #include <kern/sched_prim.h>
 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);
 }