aboutsummaryrefslogtreecommitdiff
path: root/nuttx/sched/task_exithook.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/sched/task_exithook.c')
-rw-r--r--nuttx/sched/task_exithook.c71
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);