/*
* linux/kernel/exit.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/completion.h>
#include <linux/personality.h>
#include <linux/tty.h>
#include <linux/namespace.h>
#include <linux/key.h>
#include <linux/security.h>
#include <linux/cpu.h>
#include <linux/acct.h>
#include <linux/file.h>
#include <linux/binfmts.h>
#include <linux/ptrace.h>
#include <linux/profile.h>
#include <linux/mount.h>
#include <linux/proc_fs.h>
#include <linux/mempolicy.h>
#include <linux/cpuset.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
#include <linux/cn_proc.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/pgtable.h>
#include <asm/mmu_context.h>
extern void sem_exit (void);
extern struct task_struct *child_reaper;
int getrusage(struct task_struct *, int, struct rusage __user *);
static void exit_mm(struct task_struct * tsk);
static void __unhash_process(struct task_struct *p)
{
nr_threads--;
detach_pid(p, PIDTYPE_PID);
detach_pid(p, PIDTYPE_TGID);
if (thread_group_leader(p)) {
detach_pid(p, PIDTYPE_PGID);
detach_pid(p, PIDTYPE_SID);
if (p->pid)
__get_cpu_var(process_counts)--;
}
REMOVE_LINKS(p);
}
void release_task(struct task_struct * p)
{
int zap_leader;
task_t *leader;
struct dentry *proc_dentry;
repeat:
atomic_dec(&p->user->processes);
spin_lock(&p->proc_lock);
proc_dentry = proc_pid_unhash(p);
write_lock_irq(&tasklist_lock);
if (unlikely(p->ptrace))
__ptrace_unlink(p);
BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
__exit_signal(p);
__exit_sighand(p);
/*
* Note that the fastpath in sys_times depends on __exit_signal having
* updated the counters before a task is removed from the tasklist of
* the process by __unhash_process.
*/
__unhash_process(p);
/*
* If we are the last non-leader member of the thread
* group, and the leader is zombie, then notify the
* group leader's parent process. (if it wants notification.)
*/
zap_leader = 0;
leader = p->group_leader;
if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
BUG_ON(leader->exit_signal == -1);
do_notify_parent(leader, leader->exit_signal);
/*
* If we were the last child thread and the leader has
* exited already, and the leader's parent ignores SIGCHLD,
* then we are the one who should release the leader.
*
* do_notify_parent() will have marked it self-reaping in
* that case.
*/
zap_leader = (leader->exit_signal == -1);
}
sched_exit(p);
write_unlock_irq(&tasklist_lock);
spin_unlock(&p->proc_lock);
proc_pid_flush(proc_dentry);
release_thread(p);
put_task_struct(p);
p = leader;
if (unlikely(zap_leader))
goto repeat;
}
/* we are using it only for SMP init */
void unhash_process(struct task_struct *p)
{
struct dentry *proc_dentry;
spin_lock(&p->proc_lock);
proc_dentry = proc_pid_unhash(p);
write_lock_irq(&tasklist_lock);
__unhash_process(p);
write_unlock_irq(&tasklist_lock);
spin_unlock(&p->proc_lock);
proc_pid_flush(proc_dentry);
}
/*
* This checks not only the pgrp, but falls back on the pid if no
* satisfactory pgrp is found. I dunno - gdb doesn't work correctly
* without this...
*/
int session_of_pgrp(int pgrp)
{
struct task_struct *p;
int sid = -1;
read_lock(&tasklist_lock);
do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p->signal->session > 0) {
sid = p->signal->session;
goto out;
}
} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
p = find_task_by_pid(pgrp);
if (p)
sid = p->signal->session;
out:
read_unlock(&tasklist_lock);
return sid;
}
/*
* Determine if a process group is "orphaned", according to the POSIX
* definition in 2.2.2.52. Orphaned process groups are not to be affected
* by terminal-generated stop signals. Newly orphaned process groups are
* to receive a SIGHUP and a SIGCONT.
*
* "I ask you, have you ever known what it is to be an orphan?"
*/
static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
{
struct task_struct *p;
int ret = 1;
do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p == ignored_task
|| p->exit_state
|| p->real_parent->pid == 1)
continue;
if (process_group(p->real_parent) != pgrp
&& p->real_parent->signal->session == p->signal->session) {
ret = 0;
break;
}
} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
return ret; /* (sighing) "Often!" */
}
int is_orphaned_pgrp(int pgrp)
{
int retval;
read_lock(&tasklist_lock);
retval = will_become_orphaned_pgrp(pgrp, NULL);
read_unlock(&tasklist_lock);
return retval;
}
static inline int has_stopped_jobs(int pgrp)
{
int retval = 0;
struct task_struct *p;
do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p->state != TASK_STOPPED)
continue;
/* If p is stopped by a debugger on a signal that won't
stop it, then don't count p as stopped. This isn't
perfect but it's a good approximation. */
if (unlikely (p->ptrace)
&& p->exit_code != SIGSTOP
&& p->exit_code != SIGTSTP
&& p->exit_code != SIGTTOU
&& p->exit_code != SIGTTIN)
continue;
retval = 1;
break;
} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
return retval;
}
/**
* reparent_to_init - Reparent the calling kernel thread to the init task.
*
* If a kernel thread is launched as a result of a system call, or if
* it ever exits, it should generally reparent itself to init so that
* it is correctly cleaned up on exit.
*
* The various task state such as scheduling policy and priority may have
* been inherited from a user process, so we reset them to sane values here.
*
* NOTE that reparent_to
|