#include "syslib.h" #include #include #include /* SEF Signal callbacks. */ static struct sef_cbs { sef_cb_signal_handler_t sef_cb_signal_handler; sef_cb_signal_manager_t sef_cb_signal_manager; } sef_cbs = { SEF_CB_SIGNAL_HANDLER_DEFAULT, SEF_CB_SIGNAL_MANAGER_DEFAULT }; /* SEF Signal prototypes for sef_receive(). */ int do_sef_signal_request(message *m_ptr); /* Debug. */ EXTERN char* sef_debug_header(void); /* Information about SELF. */ EXTERN endpoint_t sef_self_endpoint; /*===========================================================================* * process_sigmgr_signals * *===========================================================================*/ static void process_sigmgr_signals(void) { /* A signal manager has pending signals in the kernel. Process them. */ endpoint_t target; sigset_t sigset; int signo, r; while (TRUE) { /* Get an arbitrary pending signal. */ if((r=sys_getksig(&target, &sigset)) != OK) panic("SEF: sys_getksig failed: %d", r); if (target == NONE) { /* Stop if there are no more pending signals. */ break; } else { /* Process every signal in the signal set. */ r = OK; for (signo = SIGS_FIRST; signo <= SIGS_LAST; signo++) { int s = sigismember(&sigset, signo); assert(s >= 0); if(s) { /* Let the callback code process the signal. */ r = sef_cbs.sef_cb_signal_manager(target, signo); /* Stop if process is gone. */ if(r == EDEADSRCDST) { break; } } } /* Tell the kernel we are done if the target is still alive. */ if(r == OK) { if((r=sys_endksig(target)) != OK) panic("SEF: sys_endksig failed :%d", r); } } } } /*===========================================================================* * process_sigmgr_self_signals * *===========================================================================*/ static void process_sigmgr_self_signals(sigset_t sigset) { /* A signal manager has pending signals for itself. Process them. */ int signo; for (signo = SIGS_FIRST; signo <= SIGS_LAST; signo++) { int s = sigismember(&sigset, signo); assert(s >= 0); if(s) { /* Let the callback code process the signal. */ sef_cbs.sef_cb_signal_handler(signo); } } } /*===========================================================================* * do_sef_signal_request * *===========================================================================*/ int do_sef_signal_request(message *m_ptr) { /* Handle a SEF Signal request. */ int signo; sigset_t sigset; if(m_ptr->m_source == SYSTEM) { /* Handle kernel signals. */ sigset = m_ptr->m_notify.sigset; for (signo = SIGK_FIRST; signo <= SIGK_LAST; signo++) { int s = sigismember(&sigset, signo); assert(s >= 0); if (s) { /* Let the callback code handle the kernel signal. */ sef_cbs.sef_cb_signal_handler(signo); /* Handle SIGKSIG for a signal manager. */ if(signo == SIGKSIG) { process_sigmgr_signals(); } /* Handle SIGKSIGSM for a signal manager. */ else if(signo == SIGKSIGSM) { process_sigmgr_self_signals(sigset); } } } } else { /* Handle system signals from a signal manager. */ signo = m_ptr->m_pm_lsys_sigs_signal.num; /* Debug. */ #if SEF_SIGNAL_DEBUG sef_signal_debug_begin(); sef_signal_dprint("%s. Got a SEF Signal request for signal %d! About to handle signal.\n", sef_debug_header(), signo); sef_signal_debug_end(); #endif /* Let the callback code handle the signal. */ sef_cbs.sef_cb_signal_handler(signo); } /* Return OK not to let anybody else intercept the request. */ return OK; } /*===========================================================================* * sef_setcb_signal_handler * *===========================================================================*/ void sef_setcb_signal_handler(sef_cb_signal_handler_t cb) { assert(cb != NULL); sef_cbs.sef_cb_signal_handler = cb; } /*===========================================================================* * sef_setcb_signal_manager * *===========================================================================*/ void sef_setcb_signal_manager(sef_cb_signal_manager_t cb) { assert(cb != NULL); sef_cbs.sef_cb_signal_manager = cb; } /*===========================================================================* * sef_cb_signal_handler_null * *===========================================================================*/ void sef_cb_signal_handler_null(int signo) { } /*===========================================================================* * sef_cb_signal_manager_null * *===========================================================================*/ int sef_cb_signal_manager_null(endpoint_t target, int signo) { return OK; } /*===========================================================================* * sef_cb_signal_handler_term * *===========================================================================*/ void sef_cb_signal_handler_term(int signo) { /* Terminate in case of SIGTERM, ignore other signals. */ if(signo == SIGTERM) { sef_exit(1); } } /*===========================================================================* * sef_cb_signal_handler_posix_default * *===========================================================================*/ void sef_cb_signal_handler_posix_default(int signo) { switch(signo) { /* Ignore when possible. */ case SIGCHLD: case SIGWINCH: case SIGCONT: case SIGTSTP: case SIGTTIN: case SIGTTOU: break; /* Terminate in any other case unless it is a kernel signal. */ default: if(!IS_SIGK(signo)) { sef_exit(1); } break; } }