197 lines
6.4 KiB
C
197 lines
6.4 KiB
C
|
#include "syslib.h"
|
||
|
#include <assert.h>
|
||
|
#include <signal.h>
|
||
|
#include <minix/sysutil.h>
|
||
|
|
||
|
/* SEF Signal callbacks. */
|
||
|
PRIVATE 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(). */
|
||
|
PUBLIC _PROTOTYPE( int do_sef_signal_request, (message *m_ptr) );
|
||
|
|
||
|
/* Debug. */
|
||
|
EXTERN _PROTOTYPE( char* sef_debug_header, (void) );
|
||
|
|
||
|
/* Information about SELF. */
|
||
|
EXTERN endpoint_t sef_self_endpoint;
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* process_sigmgr_signals *
|
||
|
*===========================================================================*/
|
||
|
PRIVATE 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", 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 = 1; signo < _NSIG; signo++) {
|
||
|
if(sigismember(&sigset, signo)) {
|
||
|
/* 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", r);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* process_sigmgr_self_signals *
|
||
|
*===========================================================================*/
|
||
|
PRIVATE void process_sigmgr_self_signals(sigset_t sigset)
|
||
|
{
|
||
|
/* A signal manager has pending signals for itself. Process them. */
|
||
|
int signo;
|
||
|
|
||
|
for(signo = 1; signo < _NSIG; signo++) {
|
||
|
if(sigismember(&sigset, signo)) {
|
||
|
/* Let the callback code process the signal. */
|
||
|
sef_cbs.sef_cb_signal_handler(signo);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* do_sef_signal_request *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC 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->NOTIFY_ARG;
|
||
|
for (signo = SIGK_FIRST; signo <= SIGK_LAST; signo++) {
|
||
|
if (sigismember(&sigset, signo)) {
|
||
|
/* 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->SIGS_SIG_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 *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC 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 *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC 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 *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC void sef_cb_signal_handler_null(int signo)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* sef_cb_signal_manager_null *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC int sef_cb_signal_manager_null(endpoint_t target, int signo)
|
||
|
{
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* sef_cb_signal_handler_term *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC 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 *
|
||
|
*===========================================================================*/
|
||
|
PUBLIC 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;
|
||
|
}
|
||
|
}
|
||
|
|