/* * 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); }
/** 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(); }
/* * 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); }