diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 828d5f453f9..ebac8152ac3 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -502,8 +502,9 @@ struct task_group_s /* Simple mechanism used only when there is no support for SIGCHLD */ uint8_t tg_nwaiters; /* Number of waiters */ + uint8_t tg_waitflags; /* User flags for waitpid behavior */ sem_t tg_exitsem; /* Support for waitpid */ - int *tg_statloc; /* Location to return exit status */ + FAR int *tg_statloc; /* Location to return exit status */ #endif #ifndef CONFIG_DISABLE_PTHREAD diff --git a/include/sched.h b/include/sched.h index f63c42201ae..8309c941d24 100644 --- a/include/sched.h +++ b/include/sched.h @@ -1,7 +1,8 @@ /******************************************************************************** * include/sched.h * - * Copyright (C) 2007-2009, 2011, 2013, 2015-2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011, 2013, 2015-2016 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without diff --git a/include/sys/wait.h b/include/sys/wait.h index 500c8b51f97..b305f79b136 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/sys/wait.h * - * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -75,6 +75,7 @@ #define WEXITED (1 << 3) /* Wait for processes that have exited (2) */ #define WSTOPPED (1 << 4) /* Status for child stopped on signal (2) */ #define WNOWAIT (1 << 5) /* Keep the process in a waitable state (2) */ +#define WCLAIMED (1 << 7) /* Non-standard (For internal OS use only) */ /**************************************************************************** * Public Type Definitions diff --git a/sched/group/group.h b/sched/group/group.h index 1448e5b5ef9..f7f0bbee1f9 100644 --- a/sched/group/group.h +++ b/sched/group/group.h @@ -117,8 +117,8 @@ int group_foreachchild(FAR struct task_group_s *group, foreachchild_t handler, FAR void *arg); int group_killchildren(FAR struct task_tcb_s *tcb); #ifdef CONFIG_SIG_SIGSTOP_ACTION -int group_suspendchildren(FAR struct task_tcb_s *tcb); -int group_continue(FAR struct task_tcb_s *tcb); +int group_suspendchildren(FAR struct tcb_s *tcb); +int group_continue(FAR struct tcb_s *tcb); #endif #endif diff --git a/sched/group/group_continue.c b/sched/group/group_continue.c index 624480e089d..e6304e636a2 100644 --- a/sched/group/group_continue.c +++ b/sched/group/group_continue.c @@ -66,25 +66,20 @@ * arg - Unused * * Returned Value: - * 0 (OK) on success; a negated errno value on failure. + * 0 (OK) always * ****************************************************************************/ static int group_continue_handler(pid_t pid, FAR void *arg) { FAR struct tcb_s *rtcb; - int ret; /* Resume all threads */ rtcb = sched_gettcb(pid); - if (rtc != NULL) + if (rtcb != NULL) { - ret = sched_resume(rtcb); - if (ret < 0) - { - serr("ERROR: Failed to resume %d: %d\n", ret, pid); - } + sched_continue(rtcb); } /* Always return zero. We need to visit each member of the group*/ @@ -111,7 +106,7 @@ static int group_continue_handler(pid_t pid, FAR void *arg) * ****************************************************************************/ -int group_continue(FAR struct task_tcb_s *tcb) +int group_continue(FAR struct tcb_s *tcb) { int ret; @@ -120,7 +115,7 @@ int group_continue(FAR struct task_tcb_s *tcb) */ sched_lock(); - ret = group_foreachchild(tcb->cmn.group, group_continue_handler, NULL); + ret = group_foreachchild(tcb->group, group_continue_handler, NULL); sched_unlock(); return ret; } diff --git a/sched/group/group_killchildren.c b/sched/group/group_killchildren.c index 6193ab3bda7..595d87865ef 100644 --- a/sched/group/group_killchildren.c +++ b/sched/group/group_killchildren.c @@ -66,7 +66,7 @@ * arg - The PID of the thread to be retained. * * Returned Value: - * 0 (OK) on success; a negated errno value on failure. + * 0 (OK) always * ****************************************************************************/ diff --git a/sched/group/group_suspendchildren.c b/sched/group/group_suspendchildren.c index 27761e9414c..4d594b72eb9 100644 --- a/sched/group/group_suspendchildren.c +++ b/sched/group/group_suspendchildren.c @@ -66,14 +66,13 @@ * arg - The PID of the thread to be retained. * * Returned Value: - * 0 (OK) on success; a negated errno value on failure. + * 0 (OK) always * ****************************************************************************/ static int group_suspendchildren_handler(pid_t pid, FAR void *arg) { FAR struct tcb_s *rtcb; - int ret; /* Suspend all threads except for the one specified by the argument */ @@ -84,11 +83,7 @@ static int group_suspendchildren_handler(pid_t pid, FAR void *arg) rtcb = sched_gettcb(pid); if (rtcb != NULL) { - ret = sched_suspend(rtcb); - if (ret < 0) - { - serr("ERROR: Failed to suspend %d: %d\n", ret, pid); - } + sched_suspend(rtcb); } } @@ -117,7 +112,7 @@ static int group_suspendchildren_handler(pid_t pid, FAR void *arg) * ****************************************************************************/ -int group_suspendchildren(FAR struct task_tcb_s *tcb) +int group_suspendchildren(FAR struct tcb_s *tcb) { int ret; @@ -126,8 +121,8 @@ int group_suspendchildren(FAR struct task_tcb_s *tcb) */ sched_lock(); - ret = group_foreachchild(tcb->cmn.group, group_suspendchildren_handler, - (FAR void *)((uintptr_t)tcb->cmn.pid)); + ret = group_foreachchild(tcb->group, group_suspendchildren_handler, + (FAR void *)((uintptr_t)tcb->pid)); sched_unlock(); return ret; } diff --git a/sched/sched/sched_waitpid.c b/sched/sched/sched_waitpid.c index 9561dde19fc..76d68698143 100644 --- a/sched/sched/sched_waitpid.c +++ b/sched/sched/sched_waitpid.c @@ -1,7 +1,8 @@ /**************************************************************************** * sched/sched/sched_waitpid.c * - * Copyright (C) 2011-2013, 2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2013, 2015, 2017-2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -231,9 +232,20 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options) * others? */ - if (stat_loc != NULL && group->tg_statloc == NULL) + if (group->tg_waitflags == 0) { + /* Save the waitpid() options, setting the non-standard WCLAIMED bit to + * assure that tg_waitflags is non-zero. + */ + + group->tg_waitflags = (uint8_t)options | WCLAIMED; + + /* Save the return status location (which may be NULL) */ + group->tg_statloc = stat_loc; + + /* We are the waipid() instance that gets the return status */ + mystat = true; } @@ -267,7 +279,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options) if (mystat) { - group->tg_statloc = NULL; + group->tg_statloc = NULL; + group->tg_waitflags = 0; } errcode = -ret; diff --git a/sched/signal/sig_default.c b/sched/signal/sig_default.c index 3e510cdb7e4..e8c9550ec85 100644 --- a/sched/signal/sig_default.c +++ b/sched/signal/sig_default.c @@ -156,7 +156,7 @@ static const struct nxsig_defaction_s g_defactions[] = * Name: nxsig_null_action * * Description: - * The do-nothing default signal actin handler. + * The do-nothing default signal action handler. * * Input Parameters: * Standard signal handler parameters @@ -248,15 +248,55 @@ static void nxsig_stop_task(int signo) #ifdef HAVE_GROUP_MEMBERS /* Suspend of of the children of the task. This will not suspend the * currently running task/pthread (this_task). It will suspend the - * main thread of the task group if the this_task is a pthread. + * main thread of the task group if the this_task is a pthread. */ - group_suspendchildren((FAR struct task_tcb_s *)rtcb); + group_suspendchildren(rtcb); #endif - /* Then, finally, suspend this thread */ + /* Lock the scheudler so this thread is not pre-empted until after we + * call sched_suspend(). + */ + + sched_lock(); + +#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) + /* Notify via waitpid if any parent is waiting for this task to EXIT + * or STOP. This action is only performed if WUNTRACED is set in the + * waitpid flags. + */ + + if (group->tg_waitflags & WUNTRACED) != 0) + { + /* Return zero for exit status (we are not exiting, however) */ + + if (group->tg_statloc != NULL) + { + *group->tg_statloc = 0; + group->tg_statloc = NULL; + } + + /* tg_waitflags == 0 means that the flags are available to another + * caller of waitpid(). + */ + + group->tg_waitflags = 0; + + /* YWakeup any tasks waiting for this task to exit or stop. */ + + while (group->tg_exitsem.semcount < 0) + { + /* Wake up the thread */ + + nxsem_post(&group->tg_exitsem); + } + } +#endif + + /* Then, finally, suspend this the final thread of the task group */ sched_suspend(rtcb); + sched_unlock(); } /**************************************************************************** diff --git a/sched/task/task_exithook.c b/sched/task/task_exithook.c index 4e80b8964d7..80fb7d265b9 100644 --- a/sched/task/task_exithook.c +++ b/sched/task/task_exithook.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/task/task_exithook.c * - * Copyright (C) 2011-2013, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2013, 2015. 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -536,7 +536,9 @@ static inline void task_exitwakeup(FAR struct tcb_s *tcb, int status) { /* Yes.. Wakeup any tasks waiting for this task to exit */ - group->tg_statloc = NULL; + group->tg_statloc = NULL; + group->tg_waitflags = 0; + while (group->tg_exitsem.semcount < 0) { /* Wake up the thread */