diff --git a/TODO b/TODO index 3dcf5335e2..4810210e04 100644 --- a/TODO +++ b/TODO @@ -44,7 +44,17 @@ o Task/Scheduler (sched/) Title: CHILD PTHREAD TERMINATION Description: When a tasks exits, shouldn't all of its child pthreads also be terminated? - Status: Closed. No, this behavior will not be implemented. + + This behavior was implemented as an options controlled by the + configuration setting CONFIG_SCHED_EXIT_KILL_CHILDREN. This + option must be used with caution, however. It should not be + used unless you are certain of what you are doing. Uninformed + of this option can often lead to memory leaks since, for + example, memory allocations held by threads are not + automatically freed! + + Status: Closed. No, this behavior will not be implemented unless + specifically selected. Priority: Medium, required for good emulation of process/pthread model. The current behavior allows for the main thread of a task to exit() and any child pthreads will persist. That does raise diff --git a/sched/Kconfig b/sched/Kconfig index 4e6329855b..26037f1478 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -582,6 +582,18 @@ config SCHED_WAITPID compliant) and will enable the waitid() and wait() interfaces as well. +config SCHED_EXIT_KILL_CHILDREN + bool "Enable kill all children when exit" + default n + depends on SCHED_HAVE_PARENT && SCHED_CHILD_STATUS + ---help--- + When a task exits, all of its child threads will be killed. + + Caution: This selection should not be used unless you are certain + of what you are doing. Uninformed of this option can often lead to + memory leaks since, for example, memory allocations held by threads + are not automatically freed! + endmenu # Tasks and Scheduling menu "Pthread Options" diff --git a/sched/group/group_foreachchild.c b/sched/group/group_foreachchild.c index cc5acea19f..15aa932da8 100644 --- a/sched/group/group_foreachchild.c +++ b/sched/group/group_foreachchild.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/group/group_foreachchild.c * - * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2013, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -77,7 +77,9 @@ int group_foreachchild(FAR struct task_group_s *group, DEBUGASSERT(group); - for (i = 0; i < group->tg_nmembers; i++) + /* Visit the main thread last (if present) */ + + for (i = group->tg_nmembers - 1; i >= 0; i--) { ret = handler(group->tg_members[i], arg); if (ret != 0) diff --git a/sched/task/exit.c b/sched/task/exit.c index 582fe5a05c..433e2dc987 100644 --- a/sched/task/exit.c +++ b/sched/task/exit.c @@ -1,7 +1,8 @@ /**************************************************************************** * sched/exit.c * - * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2008, 2011-2012, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -47,6 +48,7 @@ #include #include "task/task.h" +#include "group/group.h" #include "sched/sched.h" /**************************************************************************** @@ -75,6 +77,15 @@ void exit(int status) status &= 0xff; +#ifdef CONFIG_SCHED_EXIT_KILL_CHILDREN + /* Kill all of the children of the group, preserving only this thread. + * exit() is normally called from the main thread of the task. pthreads + * exit through a different mechanism. + */ + + group_killchildren((FAR struct task_tcb_s *)tcb); +#endif + /* Perform common task termination logic. This will get called again later * through logic kicked off by _exit(). However, we need to call it before * calling _exit() in order to handle atexit() and on_exit() callbacks and diff --git a/sched/task/task_exit.c b/sched/task/task_exit.c index 5972051f9b..a942a6dd8b 100644 --- a/sched/task/task_exit.c +++ b/sched/task/task_exit.c @@ -76,7 +76,7 @@ * Returned Value: * OK on success; or ERROR on failure * - * Assumeptions: + * Assumptions: * Executing within a critical section established by the caller. * ****************************************************************************/