diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-01-23 22:23:46 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-01-23 22:23:46 +0000 |
commit | 7080c71f2b2007926d5d7728f2ff443968ebe1fc (patch) | |
tree | dbc9c30e5aec5ddcdf6f0abd2b9a9416721c9bce /nuttx/sched/sig_action.c | |
parent | 7866bca6aac68f69426b9433fa5c972b5143dde1 (diff) | |
download | px4-nuttx-7080c71f2b2007926d5d7728f2ff443968ebe1fc.tar.gz px4-nuttx-7080c71f2b2007926d5d7728f2ff443968ebe1fc.tar.bz2 px4-nuttx-7080c71f2b2007926d5d7728f2ff443968ebe1fc.zip |
Add logic to retain child task exit status if so configured
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5553 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/sched/sig_action.c')
-rw-r--r-- | nuttx/sched/sig_action.c | 157 |
1 files changed, 99 insertions, 58 deletions
diff --git a/nuttx/sched/sig_action.c b/nuttx/sched/sig_action.c index fef5f1558..708667993 100644 --- a/nuttx/sched/sig_action.c +++ b/nuttx/sched/sig_action.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sig_action.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,7 @@ #include <signal.h> #include <queue.h> #include <sched.h> +#include <errno.h> #include "os_internal.h" #include "sig_internal.h" @@ -156,10 +157,11 @@ static FAR sigactq_t *sig_allocateaction(void) * Assumptions: * * POSIX Compatibility: - * - Special values of sa_handler in the struct sigaction - * act input not handled (SIG_DFL, SIG_IGN). - * - All sa_flags in struct sigaction of act input are - * ignored (all treated like SA_SIGINFO). + * - 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_CHILDSTATUS + * is defined; then SA_NOCLDWAIT is supported but only for SIGCHLD * ****************************************************************************/ @@ -167,90 +169,129 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction * { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; FAR sigactq_t *sigact; - int ret = ERROR; /* Assume failure */ + int ret; /* Since sigactions can only be installed from the running thread of * execution, no special precautions should be necessary. */ - /* Verify the signal */ + /* Verify the signal number */ - if (GOOD_SIGNO(signo)) + if (!GOOD_SIGNO(signo)) { - ret = OK; /* Assume success */ + set_errno(EINVAL); + return ERROR; + } - /* Find the signal in the sigactionq */ + /* Find the signal in the sigactionq */ - sigact = sig_findaction(rtcb, signo); + sigact = sig_findaction(rtcb, signo); - /* Return the old sigaction value if so requested */ + /* Return the old sigaction value if so requested */ - if (oact) + if (oact) + { + if (sigact) { - if (sigact) - { - COPY_SIGACTION(oact, &sigact->act); - } - else - { - /* There isn't an old value */ - - oact->sa_u._sa_handler = NULL; - oact->sa_mask = NULL_SIGNAL_SET; - oact->sa_flags = 0; - } + COPY_SIGACTION(oact, &sigact->act); + } + else + { + /* There isn't an old value */ + + oact->sa_u._sa_handler = 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 + * a given signal. + */ - /* If no sigaction was found, but one is needed, then - * allocate one. + if (!act) + { + 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. + * + * POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated + * when a child process terminates. In NuttX, a SIGCHLD signal is + * generated in this case; but in some other implementations, it may not + * be. + */ + + if (signo == SIGCHLD && (act->sa_flags & SA_NOCLDWAIT) != 0) + { + irqstate_t flags; + + /* We do require a critical section to muck with the TCB values that + * can be modified by the child thread. */ - if (!sigact && act && act->sa_u._sa_handler) - { - sigact = sig_allocateaction(); + flags = irqsave(); - /* An error has occurred if we could not allocate the sigaction */ + /* Mark that status should be not be retained */ - if (!sigact) - { - ret = ERROR; - } - else - { - /* Put the signal number in the queue entry */ + rtcb->flags |= TCB_FLAG_NOCLDWAIT; - sigact->signo = (uint8_t)signo; + /* Free all pending exit status */ - /* Add the new sigaction to sigactionq */ + task_removechildren(rtcb); + irqrestore(flags); + } +#endif - sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq); - } - } + /* Handle the case where no sigaction is supplied (SIG_IGN) */ + + if (act->sa_u._sa_handler == SIG_IGN) + { + /* If there is a old sigaction, remove it from sigactionq */ + + sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq); + + /* And deallocate it */ + + sig_releaseaction(sigact); + } - /* Set the new sigaction if so requested */ + /* A sigaction has been supplied */ - if ((sigact) && (act)) + else + { + /* Check if a sigaction was found */ + + if (!sigact) { - /* Check if it is a request to install a new handler */ + /* No sigaction was found, but one is needed. Allocate one. */ - if (act->sa_u._sa_handler) - { - COPY_SIGACTION(&sigact->act, act); - } + sigact = sig_allocateaction(); - /* No.. It is a request to remove the old handler */ + /* An error has occurred if we could not allocate the sigaction */ - else - { - /* Remove the old sigaction from sigactionq */ + if (!sigact) + { + set_errno(ENOMEM); + return ERROR; + } + + /* Put the signal number in the queue entry */ - sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq); + sigact->signo = (uint8_t)signo; - /* And deallocate it */ + /* Add the new sigaction to sigactionq */ - sig_releaseaction(sigact); - } + sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq); } + + /* Set the new sigaction */ + + COPY_SIGACTION(&sigact->act, act); } return ret; |