#include <linux/mount.h>
#include <linux/proc_fs.h>
#include <linux/mempolicy.h>
+#include <linux/ckrm.h>
+#include <linux/ckrm_tsk.h>
+#include <linux/vs_limit.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
static void __unhash_process(struct task_struct *p)
{
nr_threads--;
+ /* tasklist_lock is held, is this sufficient? */
+ if (p->vx_info) {
+ atomic_dec(&p->vx_info->cacct.nr_threads);
+ atomic_dec(&p->vx_info->limit.rcur[RLIMIT_NPROC]);
+ }
detach_pid(p, PIDTYPE_PID);
detach_pid(p, PIDTYPE_TGID);
if (thread_group_leader(p)) {
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);
ptrace_unlink(current);
/* Reparent to init */
REMOVE_LINKS(current);
+ /* FIXME handle vchild_reaper/initpid */
current->parent = child_reaper;
current->real_parent = child_reaper;
SET_LINKS(current);
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);
+ cond_resched();
+ }
+ // 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;
+ /* FIXME handle vchild_reaper/initpid */
reaper = father->group_leader;
if (reaper == father)
reaper = child_reaper;
* 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);
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);
}
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);
module_put(tsk->binfmt->module);
tsk->exit_code = code;
+#ifdef CONFIG_CKRM_TYPE_TASKCLASS
+ 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". */
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);