diff --git a/include/signal.h b/include/signal.h index 883349bd75..e95cb58c7a 100644 --- a/include/signal.h +++ b/include/signal.h @@ -242,9 +242,15 @@ */ #define SIG_ERR ((_sa_handler_t)-1) /* And error occurred */ -#define SIG_DFL ((_sa_handler_t)0) /* Default is SIG_IGN for all signals */ #define SIG_IGN ((_sa_handler_t)0) /* Ignore the signal */ -#define SIG_HOLD ((_sa_handler_t)1) /* Used only with sigset() */ + +#ifdef CONFIG_SIG_DEFAULT +# define SIG_DFL ((_sa_handler_t)1) /* Default signal action */ +# define SIG_HOLD ((_sa_handler_t)2) /* Used only with sigset() */ +#else +# define SIG_DFL ((_sa_handler_t)0) /* Default is SIG_IGN for all signals */ +# define SIG_HOLD ((_sa_handler_t)1) /* Used only with sigset() */ +#endif /******************************************************************************** * Public Type Definitions diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c index 30d524f611..9dd041a51f 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/signal/sig_action.c * - * Copyright (C) 2007-2009, 2013, 2016-2017 Gregory Nutt. All rights + * Copyright (C) 2007-2009, 2013, 2016-2018 Gregory Nutt. All rights * reserved. * Author: Gregory Nutt * @@ -52,15 +52,6 @@ #include "group/group.h" #include "signal/signal.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define COPY_SIGACTION(t,f) \ - { (t)->sa_sigaction = (f)->sa_sigaction; \ - (t)->sa_mask = (f)->sa_mask; \ - (t)->sa_flags = (f)->sa_flags; } - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -154,11 +145,13 @@ static FAR sigactq_t *nxsig_alloc_action(void) * ****************************************************************************/ -int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact) +int sigaction(int signo, FAR const struct sigaction *act, + FAR struct sigaction *oact) { FAR struct tcb_s *rtcb = this_task(); FAR struct task_group_s *group; FAR sigactq_t *sigact; + _sa_sigaction_t handler; /* Since sigactions can only be installed from the running thread of * execution, no special precautions should be necessary. @@ -181,34 +174,48 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction * /* Return the old sigaction value if so requested */ - if (oact) + if (oact != NULL) { +#ifdef CONFIG_SIG_DEFAULT + if (nxsig_isdefault(rtcb, signo)) + { + /* Return SIG_DFL if the default signal is attached */ + + oact->sa_sigaction = (_sa_sigaction_t)SIG_DFL; + oact->sa_mask = NULL_SIGNAL_SET; + oact->sa_flags = SA_SIGINFO; + } + else +#endif if (sigact) { - COPY_SIGACTION(oact, &sigact->act); + /* Return the old signal action */ + + oact->sa_sigaction = sigact->act.sa_sigaction; + oact->sa_mask = sigact->act.sa_mask; + oact->sa_flags = sigact->act.sa_flags; } else { /* There isn't an old value */ - oact->sa_u._sa_handler = NULL; - oact->sa_mask = NULL_SIGNAL_SET; - oact->sa_flags = 0; + oact->sa_sigaction = NULL; + oact->sa_mask = NULL_SIGNAL_SET; + oact->sa_flags = 0; } } /* If the argument act is a null pointer, signal handling is unchanged; - * thus, the call can be used to enquire about the current handling of + * thus, the call can be used to inquire about the current handling of * a given signal. */ - if (!act) + if (act == NULL) { return OK; } #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) - /* Handle a special case. Retention of child status can be suppressed * if signo == SIGCHLD and sa_flags == SA_NOCLDWAIT. * @@ -239,9 +246,30 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction * } #endif + handler = act->sa_sigaction; + +#ifdef CONFIG_SIG_DEFAULT + /* If the caller is setting the handler to SIG_DFL, then we need to + * replace this with the correct, internal default signal action handler. + */ + + if (handler == (_sa_sigaction_t)SIG_DFL) + { + /* nxsig_default() may returned SIG_IGN */ + + handler = nxsig_default(rtcb, signo, true); + } + else + { + /* We will be replacing the default action (or ignoring it) */ + + (void)nxsig_default(rtcb, signo, false); + } +#endif + /* Handle the case where no sigaction is supplied (SIG_IGN) */ - if (act->sa_u._sa_handler == SIG_IGN) + if (handler == (_sa_sigaction_t)SIG_IGN) { /* Do we still have a sigaction container from the previous setting? */ @@ -265,7 +293,7 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction * * If so, then re-use for the new signal action. */ - if (!sigact) + if (sigact == NULL) { /* No.. Then we need to allocate one for the new action. */ @@ -290,7 +318,9 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction * /* Set the new sigaction */ - COPY_SIGACTION(&sigact->act, act); + sigact->act.sa_sigaction = handler; + sigact->act.sa_mask = act->sa_mask; + sigact->act.sa_flags = act->sa_flags; } return OK; diff --git a/sched/signal/sig_default.c b/sched/signal/sig_default.c index 0596a82b99..6d99165de7 100644 --- a/sched/signal/sig_default.c +++ b/sched/signal/sig_default.c @@ -112,67 +112,6 @@ static void nxsig_abnormal_termination(int signo, FAR siginfo_t *siginfo, exit(EXIT_FAILURE); } -/**************************************************************************** - * Name: nxsig_setup_default_action - * - * Description: - * Setup the default action for the SIGKILL signal - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void nxsig_setup_default_action(FAR struct tcb_s *tcb, - _sa_sigaction_t action, int signo) -{ - FAR struct task_group_s *group; - struct sigaction sa; - - DEBUGASSERT(tcb != NULL && tcb->group != NULL && GOOD_SIGNO(signo)); - group = tcb->group; - - /* Attach the signal handler */ - - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = action; - sa.sa_flags = SA_SIGINFO; - (void)sigaction(SIGKILL, &sa, NULL); - - /* Indicate that the default signal handler has been attached */ - - (void)sigaddset(&group->tg_sigdefault, signo); -} - -/**************************************************************************** - * Name: nxsig_setup_default_action - * - * Description: - * Setup the default action for the SIGKILL signal - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void nxsig_unsetup_default_action(FAR struct tcb_s *tcb, int signo) -{ - FAR struct task_group_s *group; - - DEBUGASSERT(tcb != NULL && tcb->group != NULL && GOOD_SIGNO(signo)); - group = tcb->group; - - /* Indicate that the default signal handler has been replaced */ - - (void)sigdelset(&group->tg_sigdefault, signo); -} - /**************************************************************************** * Name: nxsig_default_action * @@ -198,6 +137,48 @@ static _sa_sigaction_t nxsig_default_action(int signo) #endif } +/**************************************************************************** + * Name: nxsig_setup_default_action + * + * Description: + * Setup the default action for the SIGKILL signal + * + * Input Parameters: + * group - The group that the task belongs in. + * action - The new default signal action + * signo - The signal that will produce this default action + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nxsig_setup_default_action(FAR struct task_group_s *group, + int signo) +{ + struct sigaction sa; + _sa_sigaction_t action; + + DEBUGASSERT(group != NULL && GOOD_SIGNO(signo)); + + /* Get the address of the handler for this signals default action. */ + + action = nxsig_default_action(signo); + if (action != (_sa_sigaction_t)SIG_IGN) + { + /* Attach the signal handler */ + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = action; + sa.sa_flags = SA_SIGINFO; + (void)sigaction(SIGKILL, &sa, NULL); + + /* Indicate that the default signal handler has been attached */ + + (void)sigaddset(&group->tg_sigdefault, signo); + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -235,10 +216,17 @@ bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo) } /**************************************************************************** - * Name: nxsig_setdefault + * Name: nxsig_default * * Description: - * Set the default action for the specified signal + * If 'defaction' is true, then return the default signal handler action + * for the specified signal and mark that the default signal hander is + * in place (it is not yet). + * + * If 'defaction' is false, then mark that the default signal handler is + * NOT in place and return SIG_IGN. + * + * This function is called form sigaction() to handle actions = SIG_DFL. * * Input Parameters: * tcb - Identifies the thread associated with the default handler @@ -246,13 +234,20 @@ bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo) * defaction - True: the default action is in place * * Returned Value: - * Zero (OK) is returned on success; A negated errno value is returned - * on failure. + * The address of the default signal action handler is returne on success. + * SIG_IGN is returned if there is no default action. * ****************************************************************************/ -int nxsig_default(FAR struct tcb_s *tcb, int signo, bool defaction) + _sa_sigaction_t nxsig_default(FAR struct tcb_s *tcb, int signo, + bool defaction) { + FAR struct task_group_s *group; + _sa_sigaction_t handler = (_sa_sigaction_t)SIG_IGN; + + DEBUGASSERT(tcb != NULL && tcb->group != NULL); + group = tcb->group; + /* Are we setting or unsetting the default action? */ if (defaction) @@ -261,27 +256,29 @@ int nxsig_default(FAR struct tcb_s *tcb, int signo, bool defaction) * associated with signo. */ - _sa_sigaction_t handler = nxsig_default_action(signo); - if (handler != NULL) + handler = nxsig_default_action(signo); + if (handler != (_sa_sigaction_t)SIG_IGN) { - nxsig_setup_default_action(tcb, handler, signo); + (void)sigaddset(&group->tg_sigdefault, signo); } } - else + + if (handler == (_sa_sigaction_t)SIG_IGN) { /* We are unsetting the default action */ - nxsig_unsetup_default_action(tcb, SIGKILL); + (void)sigdelset(&group->tg_sigdefault, signo); } - return OK; + return handler; } /**************************************************************************** * Name: nxsig_default_initialize * * Description: - * Set all signals to their default action. + * Set all signals to their default action. This is called from task_start + * to configure the newly started task. * * Input Parameters: * tcb - Identifies the thread associated with the default handlers @@ -294,7 +291,31 @@ int nxsig_default(FAR struct tcb_s *tcb, int signo, bool defaction) int nxsig_default_initialize(FAR struct tcb_s *tcb) { - /* Currently only SIGKILL is supported */ + FAR struct task_group_s *group; - return nxsig_default(tcb, SIGKILL, true); + DEBUGASSERT(tcb != NULL && tcb->group != NULL); + group = tcb->group; + + /* Initialize the set of default signal handlers */ + + (void)sigemptyset(&group->tg_sigdefault); + +#if 0 + /* TODO Currently only SIGKILL is supported. The following needs to be + * in a loop that instantiates the default action for all signals (other + * that those that are ignored). + */ + + for (signo = 0; signo <= MAX_SIGNO; signo++) + { + nxsig_setup_default_action(group, signo); + } + +#else + /* For now */ + + nxsig_setup_default_action(group, SIGKILL); +#endif + + return OK; } diff --git a/sched/signal/signal.h b/sched/signal/signal.h index 0b15225d02..dce8961db9 100644 --- a/sched/signal/signal.h +++ b/sched/signal/signal.h @@ -174,7 +174,8 @@ void nxsig_release_action(FAR sigactq_t *sigact); #ifdef CONFIG_SIG_DEFAULT bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo); -int nxsig_default(FAR struct tcb_s *tcb, int signo, bool defaction); +_sa_sigaction_t nxsig_default(FAR struct tcb_s *tcb, int signo, + bool defaction); int nxsig_default_initialize(FAR struct tcb_s *tcb); #endif