mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-09 14:07:34 +02:00
forgot to add signal.c used by process.stub
This commit is contained in:
parent
77f2990f28
commit
4e5889a6f4
1 changed files with 59 additions and 0 deletions
59
lib/chibi/signal.c
Normal file
59
lib/chibi/signal.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
#define SEXP_MAX_SIGNUM 32
|
||||
|
||||
static sexp sexp_signal_contexts[SEXP_MAX_SIGNUM];
|
||||
|
||||
static void sexp_call_sigaction (int signum, siginfo_t *info, void *uctx) {
|
||||
sexp ctx, sigctx, handler;
|
||||
sexp_gc_var1(args);
|
||||
ctx = sexp_signal_contexts[signum];
|
||||
if (ctx) {
|
||||
handler = sexp_vector_ref(sexp_global(ctx, SEXP_G_SIGNAL_HANDLERS),
|
||||
sexp_make_fixnum(signum));
|
||||
if (sexp_truep(handler)) {
|
||||
sigctx = sexp_make_child_context(ctx, NULL);
|
||||
sexp_gc_preserve1(sigctx, args);
|
||||
args = sexp_cons(sigctx, SEXP_FALSE, SEXP_NULL);
|
||||
sexp_car(args)
|
||||
= sexp_make_cpointer(sigctx, sexp_siginfo_type_id, info, SEXP_FALSE, 0);
|
||||
args = sexp_cons(sigctx, SEXP_FALSE, args);
|
||||
sexp_car(args) = sexp_make_fixnum(signum);
|
||||
sexp_apply(sigctx, handler, args);
|
||||
sexp_gc_release1(sigctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct sigaction call_sigaction = {
|
||||
.sa_sigaction = sexp_call_sigaction,
|
||||
.sa_flags = SA_SIGINFO | SA_NODEFER
|
||||
};
|
||||
|
||||
static struct sigaction call_sigdefault = {.sa_handler = SIG_DFL};
|
||||
static struct sigaction call_sigignore = {.sa_handler = SIG_IGN};
|
||||
|
||||
static sexp sexp_set_signal_action (sexp ctx, sexp signum, sexp newaction) {
|
||||
int res;
|
||||
sexp oldaction;
|
||||
if (! (sexp_fixnump(signum) && sexp_unbox_fixnum(signum) > 0
|
||||
&& sexp_unbox_fixnum(signum) < SEXP_MAX_SIGNUM))
|
||||
return sexp_type_exception(ctx, "not a valid signal number", signum);
|
||||
if (! (sexp_procedurep(newaction) || sexp_opcodep(newaction)
|
||||
|| sexp_booleanp(newaction)))
|
||||
return sexp_type_exception(ctx, "not a procedure", newaction);
|
||||
if (! sexp_vectorp(sexp_global(ctx, SEXP_G_SIGNAL_HANDLERS)))
|
||||
sexp_global(ctx, SEXP_G_SIGNAL_HANDLERS)
|
||||
= sexp_make_vector(ctx, sexp_make_fixnum(SEXP_MAX_SIGNUM), SEXP_FALSE);
|
||||
oldaction = sexp_vector_ref(sexp_global(ctx, SEXP_G_SIGNAL_HANDLERS), signum);
|
||||
res = sigaction(sexp_unbox_fixnum(signum),
|
||||
(sexp_booleanp(newaction) ?
|
||||
(sexp_truep(newaction) ? &call_sigdefault : &call_sigignore)
|
||||
: &call_sigaction),
|
||||
NULL);
|
||||
if (res)
|
||||
return sexp_user_exception(ctx, SEXP_FALSE, "couldn't set signal", signum);
|
||||
sexp_vector_set(sexp_global(ctx, SEXP_G_SIGNAL_HANDLERS), signum, newaction);
|
||||
sexp_signal_contexts[sexp_unbox_fixnum(signum)] = ctx;
|
||||
return oldaction;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue