summaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
commit967c65a99059fd459b956c1588ce0ba227912c4e (patch)
tree8224d013ff5d255420713d05610c7efebd204d2a /kernel/exit.c
parente20c1cc1656a66a2773bca4591a895cbc12696ff (diff)
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c220
1 files changed, 8 insertions, 212 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 5ed96a90d..a01317af8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -20,113 +20,17 @@
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/acct.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/mmu_context.h>
extern void sem_exit (void);
-extern void acct_process (long exitcode);
extern void kerneld_exit(void);
int getrusage(struct task_struct *, int, struct rusage *);
-static inline void generate(unsigned long sig, struct task_struct * p)
-{
- unsigned flags;
- unsigned long mask = 1 << (sig-1);
- struct sigaction * sa = sig + p->sig->action - 1;
-
- /*
- * Optimize away the signal, if it's a signal that can
- * be handled immediately (ie non-blocked and untraced)
- * and that is ignored (either explicitly or by default)
- */
- spin_lock_irqsave(&p->sig->siglock, flags);
- if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
- /* don't bother with ignored signals (but SIGCHLD is special) */
- if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
- goto out;
- /* some signals are ignored by default.. (but SIGCONT already did its deed) */
- if ((sa->sa_handler == SIG_DFL) &&
- (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
- goto out;
- }
- spin_lock(&p->sigmask_lock);
- p->signal |= mask;
- spin_unlock(&p->sigmask_lock);
- if (p->state == TASK_INTERRUPTIBLE && signal_pending(p))
- wake_up_process(p);
-out:
- spin_unlock_irqrestore(&p->sig->siglock, flags);
-}
-
-/*
- * Force a signal that the process can't ignore: if necessary
- * we unblock the signal and change any SIG_IGN to SIG_DFL.
- */
-void force_sig(unsigned long sig, struct task_struct * p)
-{
- sig--;
- if (p->sig) {
- unsigned flags;
- unsigned long mask = 1UL << sig;
- struct sigaction *sa = p->sig->action + sig;
-
- spin_lock_irqsave(&p->sig->siglock, flags);
-
- spin_lock(&p->sigmask_lock);
- p->signal |= mask;
- p->blocked &= ~mask;
- spin_unlock(&p->sigmask_lock);
-
- if (sa->sa_handler == SIG_IGN)
- sa->sa_handler = SIG_DFL;
- if (p->state == TASK_INTERRUPTIBLE)
- wake_up_process(p);
-
- spin_unlock_irqrestore(&p->sig->siglock, flags);
- }
-}
-
-int send_sig(unsigned long sig,struct task_struct * p,int priv)
-{
- if (!p || sig > 32)
- return -EINVAL;
- if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
- (current->euid ^ p->suid) && (current->euid ^ p->uid) &&
- (current->uid ^ p->suid) && (current->uid ^ p->uid) &&
- !suser())
- return -EPERM;
-
- if (sig && p->sig) {
- unsigned flags;
- spin_lock_irqsave(&p->sigmask_lock, flags);
- if ((sig == SIGKILL) || (sig == SIGCONT)) {
- if (p->state == TASK_STOPPED)
- wake_up_process(p);
- p->exit_code = 0;
- p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
- (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
- }
- if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
- p->signal &= ~(1<<(SIGCONT-1));
- spin_unlock_irqrestore(&p->sigmask_lock, flags);
-
- /* Actually generate the signal */
- generate(sig,p);
- }
- return 0;
-}
-
-void notify_parent(struct task_struct * tsk, int signal)
-{
- struct task_struct * parent = tsk->p_pptr;
-
- send_sig(signal, parent, 1);
- wake_up_interruptible(&parent->wait_chldexit);
-}
-
void release(struct task_struct * p)
{
if (p != current) {
@@ -179,118 +83,6 @@ int session_of_pgrp(int pgrp)
}
/*
- * kill_pg() sends a signal to a process group: this is what the tty
- * control characters do (^C, ^Z etc)
- */
-int kill_pg(int pgrp, int sig, int priv)
-{
- int retval;
-
- retval = -EINVAL;
- if (sig >= 0 && sig <= 32 && pgrp > 0) {
- struct task_struct *p;
- int found = 0;
-
- retval = -ESRCH;
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->pgrp == pgrp) {
- int err = send_sig(sig,p,priv);
- if (err != 0)
- retval = err;
- else
- found++;
- }
- }
- read_unlock(&tasklist_lock);
- if (found)
- retval = 0;
- }
- return retval;
-}
-
-/*
- * kill_sl() sends a signal to the session leader: this is used
- * to send SIGHUP to the controlling process of a terminal when
- * the connection is lost.
- */
-int kill_sl(int sess, int sig, int priv)
-{
- int retval;
-
- retval = -EINVAL;
- if (sig >= 0 && sig <= 32 && sess > 0) {
- struct task_struct *p;
- int found = 0;
-
- retval = -ESRCH;
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->leader && p->session == sess) {
- int err = send_sig(sig,p,priv);
-
- if (err)
- retval = err;
- else
- found++;
- }
- }
- read_unlock(&tasklist_lock);
- if (found)
- retval = 0;
- }
- return retval;
-}
-
-int kill_proc(int pid, int sig, int priv)
-{
- int retval;
-
- retval = -EINVAL;
- if (sig >= 0 && sig <= 32) {
- struct task_struct *p = find_task_by_pid(pid);
-
- if(p)
- retval = send_sig(sig, p, priv);
- else
- retval = -ESRCH;
- }
- return retval;
-}
-
-/*
- * POSIX specifies that kill(-1,sig) is unspecified, but what we have
- * is probably wrong. Should make it like BSD or SYSV.
- */
-asmlinkage int sys_kill(int pid,int sig)
-{
- if (!pid)
- return kill_pg(current->pgrp,sig,0);
-
- if (pid == -1) {
- int retval = 0, count = 0;
- struct task_struct * p;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->pid > 1 && p != current) {
- int err;
- ++count;
- if ((err = send_sig(sig,p,0)) != -EPERM)
- retval = err;
- }
- }
- read_unlock(&tasklist_lock);
- return count ? retval : -ESRCH;
- }
- if (pid < 0)
- return kill_pg(-pid,sig,0);
-
- /* Normal kill */
- return kill_proc(pid,sig,0);
-}
-
-/*
* 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
@@ -398,7 +190,7 @@ static inline void __exit_files(struct task_struct *tsk)
void exit_files(struct task_struct *tsk)
{
- __exit_files(tsk);
+ __exit_files(tsk);
}
static inline void __exit_fs(struct task_struct *tsk)
@@ -417,7 +209,7 @@ static inline void __exit_fs(struct task_struct *tsk)
void exit_fs(struct task_struct *tsk)
{
- __exit_fs(tsk);
+ __exit_fs(tsk);
}
static inline void __exit_sighand(struct task_struct *tsk)
@@ -429,6 +221,8 @@ static inline void __exit_sighand(struct task_struct *tsk)
if (atomic_dec_and_test(&sig->count))
kfree(sig);
}
+
+ flush_signals(tsk);
}
void exit_sighand(struct task_struct *tsk)
@@ -527,9 +321,11 @@ NORET_TYPE void do_exit(long code)
{
if (in_interrupt())
printk("Aiee, killing interrupt handler\n");
+ if (current == task[0])
+ panic("Attempted to kill the idle task!");
fake_volatile:
- acct_process(code);
current->flags |= PF_EXITING;
+ acct_process(code);
del_timer(&current->real_timer);
sem_exit();
kerneld_exit();