sched/signal: Default Signal Actions. Change some types to superficially simplify. Add configuration options to enabled default signal behaviors on a per-signal basis. I don't think users are prepared for SIGALRM to terminate the task (which is the correct default behavior if you don't change it). Extend the implementation of default signals so that it is totally table driven and extensible by simply mondifying the content of const tables.

This commit is contained in:
Gregory Nutt 2018-08-27 15:37:43 -06:00
parent a02f919bec
commit 499b89feed
5 changed files with 145 additions and 63 deletions

View File

@ -146,11 +146,11 @@
# define SIGUSR2 CONFIG_SIG_SIGUSR2
#endif
#ifndef CONFIG_SIG_SIGALARM
#ifndef CONFIG_SIG_SIGALRM
# define SIGALRM 3 /* Default signal used with POSIX timers (used only */
/* no other signal is provided) */
#else
# define SIGALRM CONFIG_SIG_SIGALARM
# define SIGALRM CONFIG_SIG_SIGALRM
#endif
#ifdef CONFIG_SCHED_HAVE_PARENT

View File

@ -1186,18 +1186,53 @@ config SIG_EVTHREAD
different mechanism would need to be development to support this
feature on the PROTECTED or KERNEL build.
config SIG_DEFAULT
menuconfig SIG_DEFAULT
bool "Default signal actions"
default n
depends on !DISABLE_SIGNALS
---help---
Enable to support default signal actions.
NOTE: SIGKILL is the only signal currently supported.
if SIG_DEFAULT
comment "Per-signal Default Actions"
config SIG_SIGUSR1_ACTION
bool "SIGUSR1"
default n
---help---
Enable the default action for SIGUSR1 (terminate the process)
Make sure that your applications are expecting this POSIX behavior.
config SIG_SIGUSR2_ACTION
bool "SIGUSR2"
default n
---help---
Enable the default action for SIGUSR2 (terminate the process)
Make sure that your applications are expecting this POSIX behavior.
config SIG_SIGALRM_ACTION
bool "SIGALRM"
default n
---help---
Enable the default action for SIGALRM (terminate the process)
Make sure that your applications are expecting this POSIX behavior.
config SIG_SIGPOLL_ACTION
bool "SIGPOLL"
default n
depends on FS_AIO
---help---
Enable the default action for SIGPOLL (terminate the process)
Make sure that your applications are expecting this POSIX behavior.
endif # SIG_DEFAULT
menu "Signal Numbers"
depends on !DISABLE_SIGNALS
comment "Standard Signal Numbers"
config SIG_SIGUSR1
int "SIGUSR1"
default 1
@ -1210,7 +1245,7 @@ config SIG_SIGUSR2
---help---
Value of standard user signal 2 (SIGUSR2). Default: 2
config SIG_SIGALARM
config SIG_SIGALRM
int "SIGALRM"
default 3
---help---
@ -1242,6 +1277,8 @@ config SIG_KILL
The SIGKILL signal is sent to cause a task termination event (only
if CONFIG_SIG_DEFAULT=y)
comment "Non-standard Signal Numbers"
config SIG_SIGCONDTIMEDOUT
int "SIGCONDTIMEDOUT"
default 16

View File

@ -151,7 +151,7 @@ int sigaction(int signo, FAR const struct sigaction *act,
FAR struct tcb_s *rtcb = this_task();
FAR struct task_group_s *group;
FAR sigactq_t *sigact;
_sa_sigaction_t handler;
_sa_handler_t handler;
/* Since sigactions can only be installed from the running thread of
* execution, no special precautions should be necessary.
@ -181,9 +181,9 @@ int sigaction(int signo, FAR const struct sigaction *act,
{
/* 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;
oact->sa_handler = SIG_DFL;
oact->sa_mask = NULL_SIGNAL_SET;
oact->sa_flags = SA_SIGINFO;
}
else
#endif
@ -191,17 +191,17 @@ int sigaction(int signo, FAR const struct sigaction *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;
oact->sa_handler = sigact->act.sa_handler;
oact->sa_mask = sigact->act.sa_mask;
oact->sa_flags = sigact->act.sa_flags;
}
else
{
/* There isn't an old value */
oact->sa_sigaction = NULL;
oact->sa_mask = NULL_SIGNAL_SET;
oact->sa_flags = 0;
oact->sa_handler = NULL;
oact->sa_mask = NULL_SIGNAL_SET;
oact->sa_flags = 0;
}
}
@ -246,14 +246,14 @@ int sigaction(int signo, FAR const struct sigaction *act,
}
#endif
handler = act->sa_sigaction;
handler = act->sa_handler;
#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)
if (handler == SIG_DFL)
{
/* nxsig_default() may returned SIG_IGN */
@ -269,7 +269,7 @@ int sigaction(int signo, FAR const struct sigaction *act,
/* Handle the case where no sigaction is supplied (SIG_IGN) */
if (handler == (_sa_sigaction_t)SIG_IGN)
if (handler == SIG_IGN)
{
/* Do we still have a sigaction container from the previous setting? */
@ -318,9 +318,9 @@ int sigaction(int signo, FAR const struct sigaction *act,
/* Set the new sigaction */
sigact->act.sa_sigaction = handler;
sigact->act.sa_mask = act->sa_mask;
sigact->act.sa_flags = act->sa_flags;
sigact->act.sa_handler = handler;
sigact->act.sa_mask = act->sa_mask;
sigact->act.sa_flags = act->sa_flags;
}
return OK;

View File

@ -47,20 +47,64 @@
#include "signal/signal.h"
/****************************************************************************
* Private Types
****************************************************************************/
/* This type provides the default action associated with a signal */
struct nxsig_defaction_s
{
uint8_t signo; /* Signal number. Range 1..MAX_SIGNO */
_sa_handler_t action; /* Default signal action */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Default actions */
static void nxsig_abnormal_termination(int signo);
/* Helpers */
static _sa_handler_t nxsig_default_action(int signo);
static void nxsig_setup_default_action(FAR struct task_group_s *group,
FAR const struct nxsig_defaction_s *info);
/****************************************************************************
* Private Data
****************************************************************************/
/* This table is used to make the default action for a signal to the correct
* signal handler.
/* NOTE: Default actions are not currently supported for very many signals.
* However, this array is set up to support an indefinite number of default
* signal actions.
*/
#if 0 /* Not used */
static const struct _sa_sigaction_t g_defactions[MAX_SIGNO + 1] =
/* This table is used to make the default action for a signal to the correct
* signal handler. Signals whose default action is be ignored do not need
* to be in this table (e.g., SIGCHLD).
*/
static const struct nxsig_defaction_s g_defactions[] =
{
/* To be provided */
}
#ifdef CONFIG_SIG_SIGUSR1_ACTION
{ SIGUSR1, nxsig_abnormal_termination },
#endif
#ifdef CONFIG_SIG_SIGUSR2_ACTION
{ SIGUSR2, nxsig_abnormal_termination },
#endif
#ifdef CONFIG_SIG_SIGALRM_ACTION
{ SIGALRM, nxsig_abnormal_termination },
#endif
#ifdef CONFIG_SIG_SIGPOLL_ACTION
{ SIGPOLL, nxsig_abnormal_termination },
#endif
{ SIGKILL, nxsig_abnormal_termination }
};
#define NACTIONS (sizeof(g_defactions) / sizeof(struct nxsig_defaction_s))
/****************************************************************************
* Private Functions
@ -96,8 +140,7 @@ static const struct _sa_sigaction_t g_defactions[MAX_SIGNO + 1] =
*
****************************************************************************/
static void nxsig_abnormal_termination(int signo, FAR siginfo_t *siginfo,
FAR void *arg)
static void nxsig_abnormal_termination(int signo)
{
#ifdef HAVE_GROUP_MEMBERS
FAR struct tcb_s *tcb = (FAR struct tcb_s *)this_task();
@ -126,15 +169,25 @@ static void nxsig_abnormal_termination(int signo, FAR siginfo_t *siginfo,
*
****************************************************************************/
static _sa_sigaction_t nxsig_default_action(int signo)
static _sa_handler_t nxsig_default_action(int signo)
{
#if 0 /* Not implemented */
return g_defactions[signo];
#else
/* Currently only SIGKILL and the abnormal exit signal action are supported */
int i;
return signo == SIGKILL ? nxsig_abnormal_termination : NULL;
#endif
/* 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].action;
}
}
/* No default action */
return SIG_IGN;
}
/****************************************************************************
@ -154,28 +207,27 @@ static _sa_sigaction_t nxsig_default_action(int signo)
****************************************************************************/
static void nxsig_setup_default_action(FAR struct task_group_s *group,
int signo)
FAR const struct nxsig_defaction_s *info)
{
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)
if (info->action != SIG_IGN)
{
/* Attach the signal handler */
struct sigaction sa;
/* Attach the signal handler.
*
* NOTE: sigaction will call nxsig_default(tcb, action, false)
*/
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = action;
sa.sa_flags = SA_SIGINFO;
sa.sa_handler = info->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);
(void)sigaddset(&group->tg_sigdefault, (int)info->signo);
}
}
@ -239,11 +291,10 @@ bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo)
*
****************************************************************************/
_sa_sigaction_t nxsig_default(FAR struct tcb_s *tcb, int signo,
bool defaction)
_sa_handler_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;
_sa_handler_t handler = SIG_IGN;
DEBUGASSERT(tcb != NULL && tcb->group != NULL);
group = tcb->group;
@ -257,13 +308,13 @@ bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo)
*/
handler = nxsig_default_action(signo);
if (handler != (_sa_sigaction_t)SIG_IGN)
if (handler != SIG_IGN)
{
(void)sigaddset(&group->tg_sigdefault, signo);
}
}
if (handler == (_sa_sigaction_t)SIG_IGN)
if (handler == SIG_IGN)
{
/* We are unsetting the default action */
@ -292,6 +343,7 @@ bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo)
int nxsig_default_initialize(FAR struct tcb_s *tcb)
{
FAR struct task_group_s *group;
int i;
DEBUGASSERT(tcb != NULL && tcb->group != NULL);
group = tcb->group;
@ -300,22 +352,15 @@ int nxsig_default_initialize(FAR struct tcb_s *tcb)
(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++)
for (i = 0; i < NACTIONS; i++)
{
nxsig_setup_default_action(group, signo);
nxsig_setup_default_action(group, &g_defactions[i]);
}
#else
/* For now */
nxsig_setup_default_action(group, SIGKILL);
#endif
return OK;
}

View File

@ -174,7 +174,7 @@ void nxsig_release_action(FAR sigactq_t *sigact);
#ifdef CONFIG_SIG_DEFAULT
bool nxsig_isdefault(FAR struct tcb_s *tcb, int signo);
_sa_sigaction_t nxsig_default(FAR struct tcb_s *tcb, 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);
#endif