#include <sys/types.h>
#include <sys/signal.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#define NODEFINE
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include "sig.h"
static void pm_sigaction(int, siginfo_t*, void*);
static void
installhandler(int i)
{
struct sigaction act;
memset(&act, 0, sizeof act);
if(i==SIGCHLD)
act.sa_flags |= SA_NOCLDSTOP;
if(pm_sigtab[i].handle){
act.sa_sigaction = pm_sigaction;
act.sa_flags |= SA_SIGINFO;
}else
act.sa_handler = SIG_DFL;
sigaction(i, &act, nil);
siginterrupt(i, !pm_sigtab[i].restart);
}
static void
installhandlers(void)
{
int i;
for(i=0; i<pm_nsigtab; i++)
installhandler(i);
}
static void
default_notify(void *arg, char *msg)
{
USED(arg);
USED(msg);
pm_noted(PM_NDFLT);
}
static void (*notifyf)(void*, char*) = default_notify;
static void
pm_sigaction(int sig, siginfo_t *info, void *context)
{
int i;
Pmproc *up;
/*
* I am sure this is not supposed to be necessary.
* installhandler(sig);
*/
if(sig == SIGCHLD){
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: got SIGCHLD\n");
// pm_checkkids();
return;
}
/*
* could pass info, context to handlers
*/
USED(info);
USED(context);
if(sig < 0 || sig >= pm_nsigtab){
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: got bad signal %d\n", sig);
pm_abort();
}
up = pm_getup();
up->sigres = -1;
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: got signal %d (%s), calling handler\n", sig,
pm_sigtab[sig].desc);
if(_setjmp(up->sigbuf)==0)
(*notifyf)(nil, pm_sigtab[sig].desc);
switch(up->sigres){
default:
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: handler didn't call noted\n");
pm_abort();
case PM_NCONT:
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: handler NCONT\n");
return;
case PM_NDFLT:
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: handler NDFLT\n");
break;
}
/* default handling */
switch(sig){
case SIGURG:
case SIGSTOP:
case SIGTSTP:
case SIGCONT:
case SIGCHLD:
case SIGTTIN:
case SIGTTOU:
case SIGIO:
case SIGWINCH:
case SIGINFO:
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: ignoring signal\n");
return;
}
if(pm_debug & PmDebugNote)
pm_fprint(2, "pm_sigaction: unhandled signal, dying\n");
for(i=0; i<pm_nsigtab; i++)
signal(i, SIG_DFL);
pm_fprint(2, "%lud %s%ssuicide: %s\n",
(ulong)getpid(), argv0 ? argv0 : "", argv0 ? " " : "",
pm_sigtab[sig].desc);
pm_abort();
}
void
pm_siginit(void)
{
installhandlers();
}
int
pm_noted(int res)
{
Pmproc *up;
up = pm_getup();
up->sigres = res;
_longjmp(up->sigbuf, 1);
abort();
return -1;
}
void
pm_notejmp(void *arg, pm_jmp_buf jb, int val)
{
USED(arg);
siglongjmp(jb, val);
}
void
pm_longjmp(pm_jmp_buf jb, int val)
{
siglongjmp(jb, val);
}
int
pm_notify(void (*fn)(void*, char*))
{
if(fn == nil)
fn = default_notify;
notifyf = fn;
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1