Esempio n. 1
0
/*
 * Arrange for the real time profiling signal to be dispatched.
 */
void
realsigprof(int sysnum, int error)
{
	proc_t *p;
	klwp_t *lwp;

	if (curthread->t_rprof->rp_anystate == 0)
		return;
	p = ttoproc(curthread);
	lwp = ttolwp(curthread);
	mutex_enter(&p->p_lock);
	if (sigismember(&p->p_ignore, SIGPROF) ||
	    signal_is_blocked(curthread, SIGPROF)) {
		mutex_exit(&p->p_lock);
		return;
	}
	lwp->lwp_siginfo.si_signo = SIGPROF;
	lwp->lwp_siginfo.si_code = PROF_SIG;
	lwp->lwp_siginfo.si_errno = error;
	hrt2ts(gethrtime(), &lwp->lwp_siginfo.si_tstamp);
	lwp->lwp_siginfo.si_syscall = sysnum;
	lwp->lwp_siginfo.si_nsysarg = (sysnum > 0 && sysnum < NSYSCALL) ?
		LWP_GETSYSENT(lwp)[sysnum].sy_narg : 0;
	lwp->lwp_siginfo.si_fault = lwp->lwp_lastfault;
	lwp->lwp_siginfo.si_faddr = lwp->lwp_lastfaddr;
	lwp->lwp_lastfault = 0;
	lwp->lwp_lastfaddr = NULL;
	sigtoproc(p, curthread, SIGPROF);
	mutex_exit(&p->p_lock);
	ASSERT(lwp->lwp_cursig == 0);
	if (issig(FORREAL)) {
		psig();
	}
	mutex_enter(&p->p_lock);
	lwp->lwp_siginfo.si_signo = 0;
	bzero(curthread->t_rprof, sizeof (*curthread->t_rprof));
	mutex_exit(&p->p_lock);
}
Esempio n. 2
0
/**
   Perform the specified event. Since almost all event firings will
   not be matched by even a single event handler, we make sure to
   optimize the 'no matches' path. This means that nothing is
   allocated/initialized unless needed.
*/
static void event_fire_internal(const event_t &event)
{

    event_list_t fire;

    /*
      First we free all events that have been removed, but only if this
    		invocation of event_fire_internal is not a recursive call.
    */
    if (is_event <= 1)
        event_free_kills();

    if (events.empty())
        return;

    /*
      Then we iterate over all events, adding events that should be
      fired to a second list. We need to do this in a separate step
      since an event handler might call event_remove or
      event_add_handler, which will change the contents of the \c
      events list.
    */
    for (size_t i=0; i<events.size(); i++)
    {
        event_t *criterion = events.at(i);

        /*
          Check if this event is a match
        */
        if (event_match(*criterion, event))
        {
            fire.push_back(criterion);
        }
    }

    /*
      No matches. Time to return.
    */
    if (fire.empty())
        return;

    if (signal_is_blocked())
    {
        /* Fix for https://github.com/fish-shell/fish-shell/issues/608. Don't run event handlers while signals are blocked. */
        event_t *heap_event = new event_t(event);
        input_common_add_callback(fire_event_callback, heap_event);
        return;
    }

    /*
      Iterate over our list of matching events
    */

    for (size_t i=0; i<fire.size(); i++)
    {
        event_t *criterion = fire.at(i);
        int prev_status;

        /*
          Check if this event has been removed, if so, dont fire it
        */
        if (event_is_killed(*criterion))
            continue;

        /*
          Fire event
        */
        wcstring buffer = criterion->function_name;

        for (size_t j=0; j < event.arguments.size(); j++)
        {
            wcstring arg_esc = escape_string(event.arguments.at(j), 1);
            buffer += L" ";
            buffer += arg_esc;
        }

        // debug( 1, L"Event handler fires command '%ls'", buffer.c_str() );

        /*
          Event handlers are not part of the main flow of code, so
          they are marked as non-interactive
        */
        proc_push_interactive(0);
        prev_status = proc_get_last_status();
        parser_t &parser = parser_t::principal_parser();

        block_t *block = new event_block_t(event);
        parser.push_block(block);
        parser.eval(buffer, io_chain_t(), TOP);
        parser.pop_block();
        proc_pop_interactive();
        proc_set_last_status(prev_status);
    }

    /*
      Free killed events
    */
    if (is_event <= 1)
        event_free_kills();

}
Esempio n. 3
0
/*
 * Handle a watchpoint that occurs while doing copyin()
 * or copyout() in a system call.
 * Return non-zero if the fault or signal is cleared
 * by a debugger while the lwp is stopped.
 */
static int
sys_watchpoint(caddr_t addr, int watchcode, int ta)
{
	extern greg_t getuserpc(void);	/* XXX header file */
	k_sigset_t smask;
	register proc_t *p = ttoproc(curthread);
	register klwp_t *lwp = ttolwp(curthread);
	register sigqueue_t *sqp;
	int rval;

	/* assert no locks are held */
	/* ASSERT(curthread->t_nlocks == 0); */

	sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
	sqp->sq_info.si_signo = SIGTRAP;
	sqp->sq_info.si_code = watchcode;
	sqp->sq_info.si_addr = addr;
	sqp->sq_info.si_trapafter = ta;
	sqp->sq_info.si_pc = (caddr_t)getuserpc();

	mutex_enter(&p->p_lock);

	/* this will be tested and cleared by the caller */
	lwp->lwp_sysabort = 0;

	if (prismember(&p->p_fltmask, FLTWATCH)) {
		lwp->lwp_curflt = (uchar_t)FLTWATCH;
		lwp->lwp_siginfo = sqp->sq_info;
		stop(PR_FAULTED, FLTWATCH);
		if (lwp->lwp_curflt == 0) {
			mutex_exit(&p->p_lock);
			kmem_free(sqp, sizeof (sigqueue_t));
			return (1);
		}
		lwp->lwp_curflt = 0;
	}

	/*
	 * post the SIGTRAP signal.
	 * Block all other signals so we only stop showing SIGTRAP.
	 */
	if (signal_is_blocked(curthread, SIGTRAP) ||
	    sigismember(&p->p_ignore, SIGTRAP)) {
		/* SIGTRAP is blocked or ignored, forget the rest. */
		mutex_exit(&p->p_lock);
		kmem_free(sqp, sizeof (sigqueue_t));
		return (0);
	}
	sigdelq(p, curthread, SIGTRAP);
	sigaddqa(p, curthread, sqp);
	schedctl_finish_sigblock(curthread);
	smask = curthread->t_hold;
	sigfillset(&curthread->t_hold);
	sigdiffset(&curthread->t_hold, &cantmask);
	sigdelset(&curthread->t_hold, SIGTRAP);
	mutex_exit(&p->p_lock);

	rval = ((ISSIG_FAST(curthread, lwp, p, FORREAL))? 0 : 1);

	/* restore the original signal mask */
	mutex_enter(&p->p_lock);
	curthread->t_hold = smask;
	mutex_exit(&p->p_lock);

	return (rval);
}