diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 72d374c6f0..16aa27087f 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -141,10 +141,10 @@ config TTY_SIGINT devices. May be enabled for other serial devices using the ISIG bit in the Termios c_lflag. - REVISIT: This implementation is non-standard. The c_lflag ISIG bit - normally enables/disables INTR, QUIT, SUSP, and DSUSP character - processing. The relationship between these names, standard signals, - and typical key presses are as follows: + REVISIT: This implementation is compliant but incomplete. The + c_lflag ISIG bit normally enables/disables INTR, QUIT, SUSP, and + DSUSP character processing. The relationship between these names, + standard signals, and typical key presses are as follows: INTR SIGINT Ctrl-C ETX(0x03) Interrupt KILL SIGKILL Ctrl-U NAK(0x15) Kill diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c index 83c61724b5..5f8a20dd47 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -137,8 +137,8 @@ static FAR sigactq_t *nxsig_alloc_action(void) * Assumptions: * * POSIX Compatibility: - * - There are no default actions so the special value SIG_DFL is treated - * like SIG_IGN. + * - If CONFIG_SIG_DEFAULT is not defined, then there are no default actions + * so the special value SIG_DFL is treated like SIG_IGN. * - All sa_flags in struct sigaction of act input are ignored (all * treated like SA_SIGINFO). The one exception is if CONFIG_SCHED_CHILD_STATUS * is defined; then SA_NOCLDWAIT is supported but only for SIGCHLD @@ -168,6 +168,19 @@ int sigaction(int signo, FAR const struct sigaction *act, return ERROR; } +#ifdef CONFIG_SIG_DEFAULT + /* Check if the user is trying to catch or ignore a signal that cannot be + * caught or ignored. + */ + + if (act != NULL && + (act->sa_handler != SIG_DFL && !nxsig_iscatchable(signo))) + { + set_errno(EINVAL); + return ERROR; + } +#endif + /* Find the signal in the signal action queue */ sigact = nxsig_find_action(group, signo); diff --git a/sched/signal/sig_default.c b/sched/signal/sig_default.c index bbeb726576..ca058f78ac 100644 --- a/sched/signal/sig_default.c +++ b/sched/signal/sig_default.c @@ -48,6 +48,14 @@ #include "signal/signal.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Bit definitions for the struct nxsig_defaction_s 'flags' field */ + +#define SIG_FLAG_NOCATCH (1 << 0) /* Signal cannot be caught or ignored */ + /**************************************************************************** * Private Types ****************************************************************************/ @@ -57,6 +65,7 @@ struct nxsig_defaction_s { uint8_t signo; /* Signal number. Range 1..MAX_SIGNO */ + uint8_t flags; /* See SIG_FLAG_ definitions */ _sa_handler_t action; /* Default signal action */ }; @@ -91,19 +100,19 @@ static void nxsig_setup_default_action(FAR struct task_group_s *group, static const struct nxsig_defaction_s g_defactions[] = { #ifdef CONFIG_SIG_SIGUSR1_ACTION - { SIGUSR1, nxsig_abnormal_termination }, + { SIGUSR1, 0, nxsig_abnormal_termination }, #endif #ifdef CONFIG_SIG_SIGUSR2_ACTION - { SIGUSR2, nxsig_abnormal_termination }, + { SIGUSR2, 0, nxsig_abnormal_termination }, #endif #ifdef CONFIG_SIG_SIGALRM_ACTION - { SIGALRM, nxsig_abnormal_termination }, + { SIGALRM, 0, nxsig_abnormal_termination }, #endif #ifdef CONFIG_SIG_SIGPOLL_ACTION - { SIGPOLL, nxsig_abnormal_termination }, + { SIGPOLL, 0, nxsig_abnormal_termination }, #endif - { SIGINT, nxsig_abnormal_termination }, - { SIGKILL, nxsig_abnormal_termination } + { SIGINT, 0, nxsig_abnormal_termination }, + { SIGKILL, SIG_FLAG_NOCATCH, nxsig_abnormal_termination } }; #define NACTIONS (sizeof(g_defactions) / sizeof(struct nxsig_defaction_s)) @@ -272,6 +281,42 @@ bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo) return ret < 0 ? false : (bool)ret; } +/**************************************************************************** + * Name: nxsig_iscatchable + * + * Description: + * Return true if the specified signal can be caught or ignored. + * + * Input Parameters: + * signo - The signal number to be queried + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +bool nxsig_iscatchable(int signo) +{ + int i; + + /* Search the default action table for the entry associated with this + * signal. + */ + + for (i = 0; i < NACTIONS; i++) + { + if (g_defactions[i].signo == signo) + { + return (g_defactions[i].flags & SIG_FLAG_NOCATCH) == 0; + } + } + + /* If it is not in the table, then it is catchable */ + + return true; +} + /**************************************************************************** * Name: nxsig_default * diff --git a/sched/signal/signal.h b/sched/signal/signal.h index e45fcfa315..c6c632c556 100644 --- a/sched/signal/signal.h +++ b/sched/signal/signal.h @@ -174,6 +174,7 @@ void nxsig_release_action(FAR sigactq_t *sigact); #ifdef CONFIG_SIG_DEFAULT bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo); +bool nxsig_iscatchable(int signo); _sa_handler_t nxsig_default(FAR struct tcb_s *tcb, int signo, bool defaction); int nxsig_default_initialize(FAR struct tcb_s *tcb);