sched/signals: Update the signal default action logic to support sigaction(). signaction() must be able to handle and input action of SIG_DFL to setup the default signal action; it mast also return SIG_DFL it is replacing the default action.

This commit is contained in:
Gregory Nutt 2018-08-27 13:13:23 -06:00
parent 6c057e608b
commit 6d094e4b33
4 changed files with 158 additions and 100 deletions

View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
*
@ -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;

View File

@ -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;
}

View File

@ -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