xref: /minix/minix/lib/libsys/sef_signal.c (revision 0a6a1f1d)
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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