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:
parent
6c057e608b
commit
6d094e4b33
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user