X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=kernel%2Fexit.c;h=8c5742ebb904679546b825b47c74bba1ac92a769;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=37faf083e6f6e5b5d1d80f17839866ced5be8f5b;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/kernel/exit.c b/kernel/exit.c index 37faf083e..8c5742ebb 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -41,8 +41,7 @@ static void __unhash_process(struct task_struct *p) /* tasklist_lock is held, is this sufficient? */ if (p->vx_info) { atomic_dec(&p->vx_info->cacct.nr_threads); - vx_nproc_dec(p->vx_info); - // atomic_dec(&p->vx_info->limit.res[RLIMIT_NPROC]); + atomic_dec(&p->vx_info->limit.rcur[RLIMIT_NPROC]); } detach_pid(p, PIDTYPE_PID); detach_pid(p, PIDTYPE_TGID); @@ -304,7 +303,7 @@ int allow_signal(int sig) Let the signal code know it'll be handled, so that they don't get converted to SIGKILL or just silently dropped */ - current->sighand->action[(sig)-1].sa.sa_handler = (void *)2; + current->sighand->action[(sig)-1].sa.sa_handler = (void __user *)2; } recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); @@ -388,7 +387,7 @@ static inline void close_files(struct files_struct * files) struct file * file = xchg(&files->fd[i], NULL); if (file) filp_close(file, files); - vx_openfd_dec(i); + // vx_openfd_dec(i); } i++; set >>= 1; @@ -603,7 +602,8 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) * group, and if no such member exists, give it to * the global child reaper process (ie "init") */ -static inline void forget_original_parent(struct task_struct * father) +static inline void forget_original_parent(struct task_struct * father, + struct list_head *to_release) { struct task_struct *p, *reaper = father; struct list_head *_p, *_n; @@ -622,16 +622,34 @@ static inline void forget_original_parent(struct task_struct * father) * Search them and reparent children. */ list_for_each_safe(_p, _n, &father->children) { + int ptrace; p = list_entry(_p,struct task_struct,sibling); + + ptrace = p->ptrace; + + /* if father isn't the real parent, then ptrace must be enabled */ + BUG_ON(father != p->real_parent && !ptrace); + if (father == p->real_parent) { + /* reparent with a reaper, real father it's us */ choose_new_parent(p, reaper, child_reaper); reparent_thread(p, father, 0); } else { - ptrace_unlink (p); + /* reparent ptraced task to its real parent */ + __ptrace_unlink (p); if (p->state == TASK_ZOMBIE && p->exit_signal != -1 && thread_group_empty(p)) do_notify_parent(p, p->exit_signal); } + + /* + * if the ptraced child is a zombie with exit_signal == -1 + * we must collect it before we exit, or it will remain + * zombie forever since we prevented it from self-reap itself + * while it was being traced by us, to be able to see it in wait4. + */ + if (unlikely(ptrace && p->state == TASK_ZOMBIE && p->exit_signal == -1)) + list_add(&p->ptrace_list, to_release); } list_for_each_safe(_p, _n, &father->ptrace_children) { p = list_entry(_p,struct task_struct,ptrace_list); @@ -648,6 +666,7 @@ static void exit_notify(struct task_struct *tsk) { int state; struct task_struct *t; + struct list_head ptrace_dead, *_p, *_n; if (signal_pending(tsk) && !tsk->signal->group_exit && !thread_group_empty(tsk)) { @@ -683,8 +702,10 @@ static void exit_notify(struct task_struct *tsk) * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) */ - forget_original_parent(tsk); + INIT_LIST_HEAD(&ptrace_dead); + forget_original_parent(tsk, &ptrace_dead); BUG_ON(!list_empty(&tsk->children)); + BUG_ON(!list_empty(&tsk->ptrace_children)); /* * Check to see if any process groups have become orphaned @@ -769,6 +790,12 @@ static void exit_notify(struct task_struct *tsk) _raw_write_unlock(&tasklist_lock); local_irq_enable(); + list_for_each_safe(_p, _n, &ptrace_dead) { + list_del_init(_p); + t = list_entry(_p,struct task_struct,ptrace_list); + release_task(t); + } + /* If the process is dead, release it - nobody will wait for it */ if (state == TASK_DEAD) release_task(tsk); @@ -810,9 +837,6 @@ asmlinkage NORET_TYPE void do_exit(long code) __exit_fs(tsk); exit_namespace(tsk); exit_thread(); -#ifdef CONFIG_NUMA - mpol_free(tsk->mempolicy); -#endif if (tsk->signal->leader) disassociate_ctty(1); @@ -823,6 +847,10 @@ asmlinkage NORET_TYPE void do_exit(long code) tsk->exit_code = code; exit_notify(tsk); +#ifdef CONFIG_NUMA + mpol_free(tsk->mempolicy); + tsk->mempolicy = NULL; +#endif schedule(); BUG(); /* Avoid "noreturn function does return". */ @@ -844,10 +872,10 @@ asmlinkage long sys_exit(int error_code) do_exit((error_code&0xff)<<8); } -task_t fastcall *next_thread(task_t *p) +task_t fastcall *next_thread(const task_t *p) { - struct pid_link *link = p->pids + PIDTYPE_TGID; - struct list_head *tmp, *head = &link->pidptr->task_list; + const struct pid_link *link = p->pids + PIDTYPE_TGID; + const struct list_head *tmp, *head = &link->pidptr->task_list; #ifdef CONFIG_SMP if (!p->sighand) @@ -999,20 +1027,17 @@ static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct ru if (p->real_parent != p->parent) { __ptrace_unlink(p); p->state = TASK_ZOMBIE; - /* If this is a detached thread, this is where it goes away. */ - if (p->exit_signal == -1) { - /* release_task takes the lock itself. */ - write_unlock_irq(&tasklist_lock); - release_task (p); - } - else { + /* + * If this is not a detached task, notify the parent. If it's + * still not detached after that, don't release it now. + */ + if (p->exit_signal != -1) { do_notify_parent(p, p->exit_signal); - write_unlock_irq(&tasklist_lock); + if (p->exit_signal != -1) + p = NULL; } - p = NULL; } - else - write_unlock_irq(&tasklist_lock); + write_unlock_irq(&tasklist_lock); } if (p != NULL) release_task(p);