diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 122fadb972fc..a5bf5329ff97 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -396,7 +396,7 @@ void daemonize(const char *name, ...) current->fs = fs; atomic_inc(&fs->count); - exit_task_namespaces(current); + put_and_finalize_nsproxy(current->nsproxy); current->nsproxy = init_task.nsproxy; get_task_namespaces(current); @@ -468,7 +468,7 @@ void fastcall put_files_struct(struct files_struct *files) fdt = files_fdtable(files); if (fdt != &files->fdtab) kmem_cache_free(files_cachep, files); - call_rcu(&fdt->rcu, free_fdtable_rcu); + free_fdtable(fdt); } } @@ -597,10 +597,6 @@ choose_new_parent(struct task_struct *p, struct task_struct *reaper) static void reparent_thread(struct task_struct *p, struct task_struct *father, int traced) { - /* We don't want people slaying init. */ - if (p->exit_signal != -1) - p->exit_signal = SIGCHLD; - if (p->pdeath_signal) /* We already hold the tasklist_lock here. */ group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p); @@ -620,13 +616,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) p->parent = p->real_parent; add_parent(p); - /* If we'd notified the old parent about this child's death, - * also notify the new parent. - */ - if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 && - thread_group_empty(p)) - do_notify_parent(p, p->exit_signal); - else if (p->state == TASK_TRACED) { + if (p->state == TASK_TRACED) { /* * If it was at a trace stop, turn it into * a normal stop since it's no longer being @@ -636,6 +626,23 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) } } + /* If this is a threaded reparent there is no need to + * notify anyone anything has happened. + */ + if (p->real_parent->group_leader == father->group_leader) + return; + + /* We don't want people slaying init. */ + if (p->exit_signal != -1) + p->exit_signal = SIGCHLD; + + /* If we'd notified the old parent about this child's death, + * also notify the new parent. + */ + if (!traced && p->exit_state == EXIT_ZOMBIE && + p->exit_signal != -1 && thread_group_empty(p)) + do_notify_parent(p, p->exit_signal); + /* * process group orphan check * Case ii: Our child is in a different pgrp @@ -846,6 +853,7 @@ static void exit_notify(struct task_struct *tsk) fastcall NORET_TYPE void do_exit(long code) { struct task_struct *tsk = current; + struct nsproxy *ns; int group_dead; profile_task_exit(tsk); @@ -931,8 +939,9 @@ fastcall NORET_TYPE void do_exit(long code) tsk->exit_code = code; proc_exit_connector(tsk); + ns = preexit_task_namespaces(tsk); exit_notify(tsk); - exit_task_namespaces(tsk); + exit_task_namespaces(tsk, ns); #ifdef CONFIG_NUMA mpol_free(tsk->mempolicy); tsk->mempolicy = NULL; |