sched_exit(p);
write_unlock_irq(&tasklist_lock);
spin_unlock(&p->proc_lock);
- proc_pid_flush(proc_dentry);
+ dput(proc_dentry);
release_thread(p);
put_task_struct(p);
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);
while (set) {
if (set & 1) {
struct file * file = xchg(&files->fd[i], NULL);
- if (file)
+ if (file) {
filp_close(file, files);
- vx_openfd_dec(fd);
+ vx_openfd_dec(fd);
+ cond_resched();
+ } else {
+ vx_openfd_dec(fd);
+ }
}
i++;
set >>= 1;
* 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;
* 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);
{
int state;
struct task_struct *t;
+ struct list_head ptrace_dead, *_p, *_n;
ckrm_cb_exit(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
_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);
}
acct_process(code);
- if (current->tux_info) {
-#ifdef CONFIG_TUX_DEBUG
- printk("Possibly unexpected TUX-thread exit(%ld) at %p?\n",
- code, __builtin_return_address(0));
-#endif
- current->tux_exit();
- }
__exit_mm(tsk);
exit_sem(tsk);
__exit_fs(tsk);
exit_namespace(tsk);
exit_thread();
-#ifdef CONFIG_NUMA
- mpol_free(tsk->mempolicy);
-#endif
if (tsk->signal->leader)
disassociate_ctty(1);
numtasks_put_ref(tsk->taskclass);
#endif
exit_notify(tsk);
+#ifdef CONFIG_NUMA
+ mpol_free(tsk->mempolicy);
+ tsk->mempolicy = NULL;
+#endif
schedule();
BUG();
/* Avoid "noreturn function does return". */