1 #include "syslib.h" 2 #include <assert.h> 3 #include <signal.h> 4 #include <minix/sysutil.h> 5 6 /* SEF Signal callbacks. */ 7 static struct sef_cbs { 8 sef_cb_signal_handler_t sef_cb_signal_handler; 9 sef_cb_signal_manager_t sef_cb_signal_manager; 10 } sef_cbs = { 11 SEF_CB_SIGNAL_HANDLER_DEFAULT, 12 SEF_CB_SIGNAL_MANAGER_DEFAULT 13 }; 14 15 /* SEF Signal prototypes for sef_receive(). */ 16 int do_sef_signal_request(message *m_ptr); 17 18 /* Debug. */ 19 EXTERN char* sef_debug_header(void); 20 21 /* Information about SELF. */ 22 EXTERN endpoint_t sef_self_endpoint; 23 24 /*===========================================================================* 25 * process_sigmgr_signals * 26 *===========================================================================*/ 27 static void process_sigmgr_signals(void) 28 { 29 /* A signal manager has pending signals in the kernel. Process them. */ 30 endpoint_t target; 31 sigset_t sigset; 32 int signo, r; 33 34 while (TRUE) { 35 /* Get an arbitrary pending signal. */ 36 if((r=sys_getksig(&target, &sigset)) != OK) 37 panic("SEF: sys_getksig failed: %d", r); 38 39 if (target == NONE) { 40 /* Stop if there are no more pending signals. */ 41 break; 42 } else { 43 /* Process every signal in the signal set. */ 44 r = OK; 45 for (signo = SIGS_FIRST; signo <= SIGS_LAST; signo++) { 46 int s = sigismember(&sigset, signo); 47 assert(s >= 0); 48 if(s) { 49 /* Let the callback code process the signal. */ 50 r = sef_cbs.sef_cb_signal_manager(target, signo); 51 52 /* Stop if process is gone. */ 53 if(r == EDEADSRCDST) { 54 break; 55 } 56 } 57 } 58 /* Tell the kernel we are done if the target is still alive. */ 59 if(r == OK) { 60 if((r=sys_endksig(target)) != OK) 61 panic("SEF: sys_endksig failed :%d", r); 62 } 63 } 64 } 65 } 66 67 /*===========================================================================* 68 * process_sigmgr_self_signals * 69 *===========================================================================*/ 70 static void process_sigmgr_self_signals(sigset_t sigset) 71 { 72 /* A signal manager has pending signals for itself. Process them. */ 73 int signo; 74 75 for (signo = SIGS_FIRST; signo <= SIGS_LAST; signo++) { 76 int s = sigismember(&sigset, signo); 77 assert(s >= 0); 78 if(s) { 79 /* Let the callback code process the signal. */ 80 sef_cbs.sef_cb_signal_handler(signo); 81 } 82 } 83 } 84 85 /*===========================================================================* 86 * do_sef_signal_request * 87 *===========================================================================*/ 88 int do_sef_signal_request(message *m_ptr) 89 { 90 /* Handle a SEF Signal request. */ 91 int signo; 92 sigset_t sigset; 93 94 if(m_ptr->m_source == SYSTEM) { 95 /* Handle kernel signals. */ 96 sigset = m_ptr->m_notify.sigset; 97 for (signo = SIGK_FIRST; signo <= SIGK_LAST; signo++) { 98 int s = sigismember(&sigset, signo); 99 assert(s >= 0); 100 if (s) { 101 /* Let the callback code handle the kernel signal. */ 102 sef_cbs.sef_cb_signal_handler(signo); 103 104 /* Handle SIGKSIG for a signal manager. */ 105 if(signo == SIGKSIG) { 106 process_sigmgr_signals(); 107 } 108 /* Handle SIGKSIGSM for a signal manager. */ 109 else if(signo == SIGKSIGSM) { 110 process_sigmgr_self_signals(sigset); 111 } 112 } 113 } 114 } 115 else { 116 /* Handle system signals from a signal manager. */ 117 signo = m_ptr->m_pm_lsys_sigs_signal.num; 118 119 /* Debug. */ 120 #if SEF_SIGNAL_DEBUG 121 sef_signal_debug_begin(); 122 sef_signal_dprint("%s. Got a SEF Signal request for signal %d! About to handle signal.\n", 123 sef_debug_header(), signo); 124 sef_signal_debug_end(); 125 #endif 126 127 /* Let the callback code handle the signal. */ 128 sef_cbs.sef_cb_signal_handler(signo); 129 } 130 131 /* Return OK not to let anybody else intercept the request. */ 132 return OK; 133 } 134 135 /*===========================================================================* 136 * sef_setcb_signal_handler * 137 *===========================================================================*/ 138 void sef_setcb_signal_handler(sef_cb_signal_handler_t cb) 139 { 140 assert(cb != NULL); 141 sef_cbs.sef_cb_signal_handler = cb; 142 } 143 144 /*===========================================================================* 145 * sef_setcb_signal_manager * 146 *===========================================================================*/ 147 void sef_setcb_signal_manager(sef_cb_signal_manager_t cb) 148 { 149 assert(cb != NULL); 150 sef_cbs.sef_cb_signal_manager = cb; 151 } 152 153 /*===========================================================================* 154 * sef_cb_signal_handler_null * 155 *===========================================================================*/ 156 void sef_cb_signal_handler_null(int signo) 157 { 158 } 159 160 /*===========================================================================* 161 * sef_cb_signal_manager_null * 162 *===========================================================================*/ 163 int sef_cb_signal_manager_null(endpoint_t target, int signo) 164 { 165 return OK; 166 } 167 168 /*===========================================================================* 169 * sef_cb_signal_handler_term * 170 *===========================================================================*/ 171 void sef_cb_signal_handler_term(int signo) 172 { 173 /* Terminate in case of SIGTERM, ignore other signals. */ 174 if(signo == SIGTERM) { 175 sef_exit(1); 176 } 177 } 178 179 /*===========================================================================* 180 * sef_cb_signal_handler_posix_default * 181 *===========================================================================*/ 182 void sef_cb_signal_handler_posix_default(int signo) 183 { 184 switch(signo) { 185 /* Ignore when possible. */ 186 case SIGCHLD: 187 case SIGWINCH: 188 case SIGCONT: 189 case SIGTSTP: 190 case SIGTTIN: 191 case SIGTTOU: 192 break; 193 194 /* Terminate in any other case unless it is a kernel signal. */ 195 default: 196 if(!IS_SIGK(signo)) { 197 sef_exit(1); 198 } 199 break; 200 } 201 } 202 203