diff options
Diffstat (limited to 'jim-signal.c')
-rw-r--r-- | jim-signal.c | 99 |
1 files changed, 63 insertions, 36 deletions
diff --git a/jim-signal.c b/jim-signal.c index b760ede..7d02e68 100644 --- a/jim-signal.c +++ b/jim-signal.c @@ -16,13 +16,13 @@ #define MAX_SIGNALS_WIDE (sizeof(jim_wide) * 8) #if defined(NSIG) - #define MAX_SIGNALS ((NSIG < MAX_SIGNALS_WIDE) ? NSIG : MAX_SIGNALS_WIDE) + #define MAX_SIGNALS (int)((NSIG < MAX_SIGNALS_WIDE) ? NSIG : MAX_SIGNALS_WIDE) #else - #define MAX_SIGNALS MAX_SIGNALS_WIDE + #define MAX_SIGNALS (int)MAX_SIGNALS_WIDE #endif static jim_wide *sigloc; -static jim_wide sigsblocked; +static jim_wide sigsignored; static struct sigaction *sa_old; static struct { int status; @@ -34,16 +34,16 @@ static struct { static void signal_handler(int sig) { - /* We just remember which signals occurred. Jim_Eval() will - * notice this as soon as it can and throw an error + /* Remember which signals occurred and store in *sigloc. + * Jim_Eval() will notice this as soon as it can and throw an error */ *sigloc |= sig_to_bit(sig); } static void signal_ignorer(int sig) { - /* We just remember which signals occurred */ - sigsblocked |= sig_to_bit(sig); + /* Remember which signals occurred for access by 'signal check' */ + sigsignored |= sig_to_bit(sig); } static void signal_init_names(void) @@ -128,16 +128,6 @@ const char *Jim_SignalId(int sig) return "unknown signal"; } -const char *Jim_SignalName(int sig) -{ -#ifdef HAVE_SYS_SIGLIST - if (sig >= 0 && sig < NSIG) { - return sys_siglist[sig]; - } -#endif - return Jim_SignalId(sig); -} - /** * Given the name of a signal, returns the signal value if found, * or returns -1 (and sets an error) if not found. @@ -179,6 +169,7 @@ static int find_signal_by_name(Jim_Interp *interp, const char *name) #define SIGNAL_ACTION_HANDLE 1 #define SIGNAL_ACTION_IGNORE -1 +#define SIGNAL_ACTION_BLOCK -2 #define SIGNAL_ACTION_DEFAULT 0 static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *const *argv) @@ -204,9 +195,13 @@ static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *cons if (action == SIGNAL_ACTION_HANDLE) { sa.sa_handler = signal_handler; } - else { + else if (action == SIGNAL_ACTION_IGNORE) { sa.sa_handler = signal_ignorer; } + else { + /* SIGNAL_ACTION_BLOCK */ + sa.sa_handler = SIG_IGN; + } } /* Iterate through the provided signals */ @@ -219,6 +214,7 @@ static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *cons if (action != siginfo[sig].status) { /* Need to change the action for this signal */ switch (action) { + case SIGNAL_ACTION_BLOCK: case SIGNAL_ACTION_HANDLE: case SIGNAL_ACTION_IGNORE: if (siginfo[sig].status == SIGNAL_ACTION_DEFAULT) { @@ -256,6 +252,11 @@ static int signal_cmd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return do_signal_cmd(interp, SIGNAL_ACTION_IGNORE, argc, argv); } +static int signal_cmd_block(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_BLOCK, argc, argv); +} + static int signal_cmd_default(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return do_signal_cmd(interp, SIGNAL_ACTION_DEFAULT, argc, argv); @@ -279,7 +280,7 @@ static int signal_cmd_check(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int clear = 0; jim_wide mask = 0; - jim_wide blocked; + jim_wide ignored; if (argc > 0 && Jim_CompareStringImmediate(interp, argv[0], "-clear")) { clear++; @@ -302,17 +303,13 @@ static int signal_cmd_check(Jim_Interp *interp, int argc, Jim_Obj *const *argv) mask = ~mask; } - if ((sigsblocked & mask) == 0) { - /* No matching signals, so empty result and nothing to do */ - return JIM_OK; - } /* Be careful we don't have a race condition where signals are cleared but not returned */ - blocked = sigsblocked & mask; + ignored = sigsignored & mask; if (clear) { - sigsblocked &= ~blocked; + sigsignored &= ~ignored; } /* Set the result */ - signal_set_sigmask_result(interp, blocked); + signal_set_sigmask_result(interp, ignored); return JIM_OK; } @@ -326,9 +323,9 @@ static int signal_cmd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } } - /* If the signal is ignored (blocked) ... */ + /* If the signal is ignored ... */ if (siginfo[sig].status == SIGNAL_ACTION_IGNORE) { - sigsblocked |= sig_to_bit(sig); + sigsignored |= sig_to_bit(sig); return JIM_OK; } @@ -380,6 +377,13 @@ static const jim_subcmd_type signal_command_table[] = { -1, /* Description: Lists ignored signals, or adds to ignored signals */ }, + { "block", + "?signals ...?", + signal_cmd_block, + 0, + -1, + /* Description: Lists blocked signals, or adds to blocked signals */ + }, { "default", "?signals ...?", signal_cmd_default, @@ -404,6 +408,25 @@ static const jim_subcmd_type signal_command_table[] = { { NULL } }; +/** + * Restore default signal handling. + */ +static void JimSignalCmdDelete(Jim_Interp *interp, void *privData) +{ + int i; + if (sa_old) { + for (i = 1; i < MAX_SIGNALS; i++) { + if (siginfo[i].status != SIGNAL_ACTION_DEFAULT) { + sigaction(i, &sa_old[i], 0); + siginfo[i].status = SIGNAL_ACTION_DEFAULT; + } + } + } + Jim_Free(sa_old); + sa_old = NULL; + sigloc = NULL; +} + static int Jim_AlarmCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int ret; @@ -510,19 +533,23 @@ int Jim_signalInit(Jim_Interp *interp) if (Jim_PackageProvide(interp, "signal", "1.0", JIM_ERRMSG)) return JIM_ERR; - signal_init_names(); + Jim_CreateCommand(interp, "alarm", Jim_AlarmCmd, 0, 0); + Jim_CreateCommand(interp, "kill", Jim_KillCmd, 0, 0); + /* Sleep is slightly dubious here */ + Jim_CreateCommand(interp, "sleep", Jim_SleepCmd, 0, 0); /* Teach the jim core how to set a result from a sigmask */ interp->signal_set_result = signal_set_sigmask_result; - /* Make sure we know where to store the signals which occur */ - sigloc = &interp->sigmask; + /* Currently only the top level interp supports signals */ + if (!sigloc) { + signal_init_names(); - Jim_CreateCommand(interp, "signal", Jim_SubCmdProc, (void *)signal_command_table, NULL); - Jim_CreateCommand(interp, "alarm", Jim_AlarmCmd, 0, 0); - Jim_CreateCommand(interp, "kill", Jim_KillCmd, 0, 0); + /* Make sure we know where to store the signals which occur */ + sigloc = &interp->sigmask; + + Jim_CreateCommand(interp, "signal", Jim_SubCmdProc, (void *)signal_command_table, JimSignalCmdDelete); + } - /* Sleep is slightly dubious here */ - Jim_CreateCommand(interp, "sleep", Jim_SleepCmd, 0, 0); return JIM_OK; } |