#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);
/*
* ---
{
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);
}
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);
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;
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);
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) {
* 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
*/
act_set_astbsd(sig_thread);
thread_abort(sig_thread);
+ proc_unlock(sig_proc);
goto psigout;
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
* postsig(signum);
*/
int
-issignal(proc_t p)
+issignal_locked(proc_t p)
{
int signum, mask, prop, sigbits;
thread_t cur_act;
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);
}
/*
* 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;
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);
}
/* NOTREACHED */
out:
proc_signalend(p, 1);
- proc_unlock(p);
return(retval);
}
wakeup((caddr_t)parent);
proc_list_unlock();
}
- (void) task_suspend(p->task); /*XXX*/
+ (void) task_suspend_internal(p->task);
}
/*
* 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;
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;
}
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);
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
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 {
/*
sendsig(p, catcher, signum, returnmask, code);
}
proc_signalend(p, 1);
- proc_unlock(p);
}
/*
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) {
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);
#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;
{
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);
p->exit_thread = self;
proc_unlock(p);
- (void) task_suspend(p->task);
+
+ task_hold(p->task);
+ task_wait(p->task, FALSE);
+
proc_lock(p);
}