📄 signal.c
字号:
* current thread assumes SET_KERNEL_FLAG */void pthread_handle_pending_signals(){ pthread_t p = mac_pthread_self(); int sig; PTRACEIN; /* * handle signals pending on threads if they are unmasked and * SIGCANCEL only on an interruption point. */ if (!pthread_siggeset2set(&p->mask, &p->pending)) for (sig = 1; sig < NNSIG; sig++) if (sigismember(&p->pending, sig) && !sigismember(&p->mask, sig) && (sig != SIGCANCEL || p->state & T_INTR_POINT)) { sigdelset(&p->pending, sig); handle_thread_signal(p, sig, p->sig_info[sig].si_code); } /* * handle signals pending on process */ if (!pthread_siggeset2set(&p->mask, &pending_signals)) for (sig = 1; sig < NNSIG; sig++) if (sigismember(&pending_signals, sig) && !sigismember(&p->mask, sig)) { sigdelset(&pending_signals, sig); handle_thread_signal(p, sig, pending_code[sig]); }}/*------------------------------------------------------------*//* * pthread_init_signals - initialize signal package */void pthread_init_signals(){ int sig; struct sigaction vec;#if defined(STACK_CHECK) && defined(SIGNAL_STACK) SIGSTACK_T ss; ss.ss_sp = (char *) SA((int) pthread_tempstack_top - STACK_OFFSET); CLR_SS_ONSTACK;#ifndef STAND_ALONE if (SIGSTACK(&ss, (SIGSTACK_T *) NULL))#ifdef DEBUG dbgleon_printf( "Pthreads: Could not specify signal stack, errno %d\n", errno)#endif /* DEBUG */ ;#endif /* !STAND_ALONE */#endif PTRACEIN; /* * initialize kernel structure */ is_in_kernel = is_updating_timer = FALSE; sigemptyset(&synchronous); sigaddset(&synchronous, SIGILL); sigaddset(&synchronous, SIGABRT);#if !defined (__linux__) && !defined(__dos__) sigaddset(&synchronous, SIGEMT);#endif /* !__linux__ && !__dos__ */ sigaddset(&synchronous, SIGFPE); sigaddset(&synchronous, SIGBUS); sigaddset(&synchronous, SIGSEGV); sigemptyset((sigset_t *) &new_signals); sigemptyset(&pending_signals); sigemptyset(&handlerset); sigemptyset(&sig_handling); sigemptyset(&cantmask); sigaddset(&cantmask, SIGKILL); sigaddset(&cantmask, SIGSTOP); sigaddset(&cantmask, SIGCANCEL); sigfillset(&all_signals); sigdelset(&all_signals, SIGKILL); sigdelset(&all_signals, SIGSTOP); pthread_queue_init(&ready); pthread_queue_init(&all); pthread_queue_init(&suspend_q); pthread_queue_init(&pthread_timeout_q); (&ready)->tqh_name = "ready-queue"; (&all)->tqh_name = "all-queue"; (&suspend_q)->tqh_name = "suspend-queue"; (&pthread_timeout_q)->tqh_name = "timeout-queue"; pthread_queue_init(&dbglist_cond); pthread_queue_init(&dbglist_mutex); set_warning = "CAUTION: entering kernel again\n"; clear_warning = "CAUTION: leaving kernel again\n"; prio_warning = "CAUTION: prio violation when leaving kernel\n";#ifdef RAND_SWITCH srandom(1); pthread_n_ready = 0;#endif#ifdef STAND_ALONE sigemptyset(&proc_mask); cur_heap = (int)lreg_sp; //(&heap_start);#else /* !STAND_ALONE */ /* * no signal requests */ for (sig = 0; sig < NNSIG; sig++) { pthread_user_handler[sig].sa_handler = SIG_DFL; sigemptyset(&pthread_user_handler[sig].sa_mask); pthread_user_handler[sig].sa_flags = 0; new_code[sig] = 0; new_cond[sig] = NULL; new_scp[sig] = NULL; } /* * install universal signal handler for all signals * except for those which cannot be masked */ vec.sa_handler = sighandler; pthread_sigcpyset2set(&vec.sa_mask, &all_signals);#if (defined(_M_UNIX) && !defined(SCO5)) || defined(__dos__) vec.sa_flags = SA_SIGINFO;#else vec.sa_flags = SA_SIGINFO | SA_RESTART;#endif#ifdef __linux__ vec.sa_restorer = (void (*)(void)) NULL;#endif for (sig = 1; sig < NSIG; sig++) if (sig != SIGPROF && !sigismember(&cantmask, sig)) {#if defined(STACK_CHECK) && defined(SIGNAL_STACK) if (sig == SIGBUS || sig == SIGILL || sig == SIGSEGV) vec.sa_flags |= SA_ONSTACK;#endif if (SIGACTION(sig, &vec, (struct sigaction *) NULL))#ifdef DEBUG dbgleon_printf( "Pthreads (signal): \ Could not install handler for signal %d\n", sig)#endif ;#if defined(STACK_CHECK) && defined(SIGNAL_STACK) if (sig == SIGBUS || sig == SIGILL || sig == SIGSEGV) vec.sa_flags &= ~SA_ONSTACK;#endif }#endif /* STAND_ALONE */}#ifdef GNATint segv = FALSE;#endif /* GNAT *//*------------------------------------------------------------*//* * sigaction - install interrupt handler for a thread on a signal * return 0 if o.k., -1 otherwise * Notice: cannot mask SIGKILL, SIGSTOP, SIGCANCEL */int sigaction(sig, act, oact)int sig;SIGACTION_CONST struct sigaction *act;struct sigaction *oact;{ register pthread_t p = mac_pthread_self(); struct sigaction vec; PTRACEIN; if (sig == SIGPROF) return(SIGACTION(sig, act, oact)); if ((sigismember(&cantmask, sig) && act) || sig < 1 || sig >= NSIG) { set_errno(EINVAL); return(-1); } if (!act) { if (oact) *oact = pthread_user_handler[sig]; return(0); } if (pthread_sigismemberset2set(&act->sa_mask, &cantmask)) { set_errno(EINVAL); return(-1); } SET_KERNEL_FLAG; if (oact) *oact = pthread_user_handler[sig]; PDEBUG(PDBG_SIGNAL,"install action[%d]=0x%x",sig,act); pthread_user_handler[sig] = *act; /* * queue up mac_pthread_self() in the signal queue indicated */ if (!sigismember(&handlerset, sig)) sigaddset(&handlerset, sig); /* * dequeue pending signals on process and threads if to be ignored * or perform default action on process if default action chosen */ if (act->sa_handler == SIG_IGN || act->sa_handler == SIG_DFL) { if (sigismember(&pending_signals, sig)) { sigdelset(&pending_signals, sig); if (act->sa_handler == SIG_DFL) default_action(sig); } TAILQ_FOREACH(p, &all, pt_qelem[K_QUEUES_ALL]) { if (sigismember(&p->pending, sig)) { sigdelset(&p->pending, sig); if (act->sa_handler == SIG_DFL) default_action(sig); } } }#ifdef __dos__ signal (sig, act->sa_handler);#else SIM_SYSCALL(TRUE);#endif CLEAR_KERNEL_FLAG; return(0);}#ifdef _M_UNIX /* Added by monty for SCO 3.2V4.2 */pthread_sighandler_t sigset(sig,handler) int sig; pthread_sighandler_t handler;{ return signal(sig, handler);}#endif/* #ifndef __dos__ *//* /\*------------------------------------------------------------*\/ *//* /\* *//* * signal - install signal handler *//* *\/ *//* pthread_sighandler_t signal(sig, handler) *//* int sig; *//* pthread_sighandler_t handler; *//* { *//* struct sigaction act; *//* act.sa_handler = handler; *//* #if defined(SOLARIS) || defined(__dos__) || defined(__USE_POSIX) *//* sigemptyset(&act.sa_mask); *//* #else /\* !SOLARIS || !__dos__ *\/ *//* act.sa_mask = 0; *//* #endif /\* !SOLARIS *\/ *//* #if defined(__linux__) || defined(__FreeBSD__) || defined(_M_UNIX) *//* act.sa_flags = SA_ONESHOT | SA_NOMASK; *//* #endif *//* #ifdef __dos__ *//* act.sa_flags = 0; *//* #endif *//* #ifdef __linux__ *//* act.sa_restorer = NULL; *//* #endif /\* __linux__ || __FreeBSD__ || _M_UNIX *\/ *//* if (!sigaction(sig, &act, (struct sigaction *) NULL)) *//* return(handler); *//* else *//* return((pthread_sighandler_t)-get_errno()); *//* } *//* #endif */#if !defined(__linux__) && !defined(__dos__)#ifdef TIMEVAL_TO_TIMESPEC#define env_use environment[0]._jb#define env_decl environment#else /* !TIMEVAL_TO_TIMESPEC */#define env_use environment#define env_decl environment#endif /* !TIMEVAL_TO_TIMESPEC *//*------------------------------------------------------------*//* * pthread_setsigcontext_np - modify the signal context to return to a setjmp() * call location, i.e. simulate a longjmp() but leave the signal handler * properly. */void pthread_setsigcontext_np(scp, env_decl, val) struct context_t *scp; jmp_buf env_decl; int val;{ scp->sc_pc = env_use[THREAD_JB_PC];#if !defined (__FreeBSD__) && !defined (_M_UNIX) && !defined(__linux__) scp->sc_npc = env_use[THREAD_JB_PC] + 4;#endif#if defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH) scp->sc_pc += RETURN_OFFSET;#if !defined (__FreeBSD__) && !defined (_M_UNIX) && !defined(__linux__) scp->sc_npc += RETURN_OFFSET;#endif#endif /* defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH) */ scp->sc_sp = env_use[THREAD_JB_SP]; if (env_use[THREAD_JB_SVMASK]) pthread_sigcpyset2set(&scp->sc_mask, &env_use[THREAD_JB_MASK]); /* copy sigmasks */#if !defined (__FreeBSD__) && !defined (_M_UNIX) && !defined(__linux__) scp->sc_o0 = val; #endif}#endif /* !__linux__ *//*------------------------------------------------------------*//* * SIGPROCMASK - change or examine signal mask of process */int SIGPROCMASK(how, set, oset)int how;const sigset_t *set;sigset_t *oset;{#ifdef SVR4 return(syscall(SYS_sigprocmask, how, set, oset));#else /* !SVR4 */ sigset_t old; PTRACEIN;#ifndef STAND_ALONE#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) SYS_SIGPROCMASK (how, NULL, &proc_mask);#else proc_mask = sigblock(0);#endif#endif /* !STAND_ALONE */ if (oset) pthread_sigcpyset2set(oset, &proc_mask); if (!set) return(0); switch (how) { case SIG_BLOCK: pthread_sigaddset2set(&proc_mask, set); break; case SIG_UNBLOCK: pthread_sigdelset2set(&proc_mask, set); break; case SIG_SETMASK: pthread_sigcpyset2set(&proc_mask, set); break; default: set_errno(EINVAL); return(-1); } pthread_sigdelset2set(&proc_mask, &cantmask);#ifndef STAND_ALONE#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) SYS_SIGPROCMASK (SIG_SETMASK, &proc_mask, NULL);#else sigsetmask(proc_mask);#endif#endif /* !STAND_ALONE */ return(0);#endif /* !SVR4 */}/*------------------------------------------------------------*//* * SIGACTION - change or examine signal handlers of process */int SIGACTION(sig, act, oact)int sig;const struct sigaction *act;struct sigaction *oact;{#ifdef SVR4#if defined(SOLARIS) && defined(IO) if (sig == SIGIO) sigaction(sig, act, oact); else#endif /* SOLARIS && IO */ return(syscall(SYS_sigaction, sig, act, oact));#else /* !SVR4 */#ifndef STAND_ALONE#if defined(__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__)#ifdef TRASH#ifdef __USE_POSIX return(__sigaction(sig, act, oact));#else return(SYS_SIGACTION (sig, act, oact));#endif /* __USE_POSIX */#else return(SYS_SIGACTION (sig, act, oact));#endif#else return(sigvec(sig, act, oact)); /* cheating: structs distinct / same layout */#endif#else /* !STAND_ALONE */ set_errno(EINVAL); return(-1);#endif /* !STAND_ALONE */#endif /* !SVR4 */}/*------------------------------------------------------------*//* * SIGSUSPEND - suspend process waiting for signals */int SIGSUSPEND(set)sigset_t *set;{#ifdef SVR4 return(syscall(SYS_sigsuspend, set));#else /* !SVR4 */#ifndef STAND_ALONE#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) return (SYS_SIGSUSPEND (set));#else return(sigpause(*set));#endif#else /* !STAND_ALONE */ /* busy wait */;#endif /* !STAND_ALONE */#endif /* !SVR4 */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -