/* 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);
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);
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;
* 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;
if (signal_pending(tsk) && !tsk->signal->group_exit
&& !thread_group_empty(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);
__exit_fs(tsk);
exit_namespace(tsk);
exit_thread();
-#ifdef CONFIG_NUMA
- mpol_free(tsk->mempolicy);
-#endif
if (tsk->signal->leader)
disassociate_ctty(1);
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". */
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)
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);