diff options
Diffstat (limited to 'nuttx/sched/task_exithook.c')
-rw-r--r-- | nuttx/sched/task_exithook.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c index 3bde8fb7a..1106f2885 100644 --- a/nuttx/sched/task_exithook.c +++ b/nuttx/sched/task_exithook.c @@ -41,6 +41,7 @@ #include <stdlib.h> #include <unistd.h> +#include <signal.h> #include <debug.h> #include <errno.h> @@ -188,6 +189,70 @@ static inline void task_onexit(FAR _TCB *tcb, int status) #endif /**************************************************************************** + * Name: task_sigchild + * + * Description: + * Send the SIGCHILD signal to the parent thread + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_HAVE_PARENT +static inline void task_sigchild(FAR _TCB *tcb, int status) +{ + FAR _TCB *ptcb; + siginfo_t info; + + /* Keep things stationary through the following */ + + sched_lock(); + + /* Get the TCB of the receiving task */ + + ptcb = sched_gettcb(tcb->parent); + if (!ptcb) + { + /* The parent no longer exists... bail */ + + sched_unlock(); + return; + } + + /* Decrement the number of children from this parent */ + + DEBUGASSERT(ptcb->nchildren > 0); + ptcb->nchildren--; + + /* Set the parent to an impossible PID. We do this because under certain + * conditions, task_exithook() can be called multiple times. If this + * function is called again, sched_gettcb() will fail on the invalid + * parent PID above, nchildren will be decremented once and all will be + * well. + */ + + tcb->parent = INVALID_PROCESS_ID; + + /* Create the siginfo structure. We don't actually know the cause. That + * is a bug. Let's just say that the child task just exit-ted for now. + */ + + info.si_signo = SIGCHLD; + info.si_code = CLD_EXITED; + info.si_value.sival_ptr = NULL; + info.si_pid = tcb->pid; + info.si_status = status; + + /* Send the signal. We need to use this internal interface so that we can + * provide the correct si_code value with the signal. + */ + + (void)sig_received(ptcb, &info); + sched_unlock(); +} +#else +# define task_sigchild(tcb,status) +#endif + +/**************************************************************************** * Name: task_exitwakeup * * Description: @@ -195,7 +260,7 @@ static inline void task_onexit(FAR _TCB *tcb, int status) * ****************************************************************************/ -#ifdef CONFIG_SCHED_WAITPID +#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) static inline void task_exitwakeup(FAR _TCB *tcb, int status) { /* Wakeup any tasks waiting for this task to exit */ @@ -263,6 +328,10 @@ void task_exithook(FAR _TCB *tcb, int status) task_onexit(tcb, status); + /* Send SIGCHLD to the parent of the exit-ing task */ + + task_sigchild(tcb, status); + /* Wakeup any tasks waiting for this task to exit */ task_exitwakeup(tcb, status); |