From da737f3167a8168dc09468cf849f16c5961664ea Mon Sep 17 00:00:00 2001 From: zhangyuan7 Date: Thu, 8 Nov 2018 07:03:30 -0600 Subject: [PATCH] sched/group/group_foreachchild.c: group_foreachchild iterate by reverse order since the callback(e.g. group_killchildren) may remove the tcb from list sched Kconfig and sched/task/exit.c: Add SCHED_EXIT_KILL_CHILDREN option to kill all child threads when the main thread of a task exits. --- TODO | 12 +++++++++++- sched/Kconfig | 12 ++++++++++++ sched/group/group_foreachchild.c | 6 ++++-- sched/task/exit.c | 13 ++++++++++++- sched/task/task_exit.c | 2 +- 5 files changed, 40 insertions(+), 5 deletions(-) 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. * ****************************************************************************/