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_signal_cbs {
8 sef_cb_signal_handler_t sef_cb_signal_handler;
9 sef_cb_signal_manager_t sef_cb_signal_manager;
10 } sef_signal_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 *===========================================================================*/
process_sigmgr_signals(void)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 set;
32 int signo, r;
33
34 while (TRUE) {
35 /* Get an arbitrary pending signal. */
36 if((r=sys_getksig(&target, &set)) != 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(&set, signo);
47 assert(s >= 0);
48 if(s) {
49 /* Let the callback code process the signal. */
50 r = sef_signal_cbs.sef_cb_signal_manager(target, signo);
51
52 /* Stop if process is gone. */
53 if(r == EDEADEPT) {
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 *===========================================================================*/
process_sigmgr_self_signals(sigset_t set)70 static void process_sigmgr_self_signals(sigset_t set)
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(&set, signo);
77 assert(s >= 0);
78 if(s) {
79 /* Let the callback code process the signal. */
80 sef_signal_cbs.sef_cb_signal_handler(signo);
81 }
82 }
83 }
84
85 /*===========================================================================*
86 * do_sef_signal_request *
87 *===========================================================================*/
do_sef_signal_request(message * m_ptr)88 int do_sef_signal_request(message *m_ptr)
89 {
90 /* Handle a SEF Signal request. */
91 int signo;
92 sigset_t set;
93
94 if(m_ptr->m_source == SYSTEM) {
95 /* Handle kernel signals. */
96 set = m_ptr->m_notify.sigset;
97 for (signo = SIGK_FIRST; signo <= SIGK_LAST; signo++) {
98 int s = sigismember(&set, signo);
99 assert(s >= 0);
100 if (s) {
101 /* Let the callback code handle the kernel signal. */
102 sef_signal_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(set);
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_signal_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 *===========================================================================*/
sef_setcb_signal_handler(sef_cb_signal_handler_t cb)138 void sef_setcb_signal_handler(sef_cb_signal_handler_t cb)
139 {
140 assert(cb != NULL);
141 sef_signal_cbs.sef_cb_signal_handler = cb;
142 }
143
144 /*===========================================================================*
145 * sef_setcb_signal_manager *
146 *===========================================================================*/
sef_setcb_signal_manager(sef_cb_signal_manager_t cb)147 void sef_setcb_signal_manager(sef_cb_signal_manager_t cb)
148 {
149 assert(cb != NULL);
150 sef_signal_cbs.sef_cb_signal_manager = cb;
151 }
152
153 /*===========================================================================*
154 * sef_cb_signal_handler_null *
155 *===========================================================================*/
sef_cb_signal_handler_null(int signo)156 void sef_cb_signal_handler_null(int signo)
157 {
158 }
159
160 /*===========================================================================*
161 * sef_cb_signal_manager_null *
162 *===========================================================================*/
sef_cb_signal_manager_null(endpoint_t target,int signo)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 *===========================================================================*/
sef_cb_signal_handler_term(int signo)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 *===========================================================================*/
sef_cb_signal_handler_posix_default(int signo)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