aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-07-26 18:04:59 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-07-26 18:04:59 -0400
commitd9ecdb282c91952796b7542c4f57fd6de6948d7b (patch)
treefd4de7923968afa7d2981fb037e2255fc2cfa1e1 /kernel/exit.c
parent4ef584ba84125b67c17b5aded38e7783cd8cdef0 (diff)
parent1d1f8b377c48e5aeddaea52eba74cc0539f088cd (diff)
Merge branch 'for_rmk_13' of git://git.mnementh.co.uk/linux-2.6-im
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c53
1 files changed, 20 insertions, 33 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index ad933bb29ec7..6cdf60712bd2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -46,6 +46,7 @@
46#include <linux/resource.h> 46#include <linux/resource.h>
47#include <linux/blkdev.h> 47#include <linux/blkdev.h>
48#include <linux/task_io_accounting_ops.h> 48#include <linux/task_io_accounting_ops.h>
49#include <linux/tracehook.h>
49 50
50#include <asm/uaccess.h> 51#include <asm/uaccess.h>
51#include <asm/unistd.h> 52#include <asm/unistd.h>
@@ -162,27 +163,17 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
162 put_task_struct(container_of(rhp, struct task_struct, rcu)); 163 put_task_struct(container_of(rhp, struct task_struct, rcu));
163} 164}
164 165
165/*
166 * Do final ptrace-related cleanup of a zombie being reaped.
167 *
168 * Called with write_lock(&tasklist_lock) held.
169 */
170static void ptrace_release_task(struct task_struct *p)
171{
172 BUG_ON(!list_empty(&p->ptraced));
173 ptrace_unlink(p);
174 BUG_ON(!list_empty(&p->ptrace_entry));
175}
176 166
177void release_task(struct task_struct * p) 167void release_task(struct task_struct * p)
178{ 168{
179 struct task_struct *leader; 169 struct task_struct *leader;
180 int zap_leader; 170 int zap_leader;
181repeat: 171repeat:
172 tracehook_prepare_release_task(p);
182 atomic_dec(&p->user->processes); 173 atomic_dec(&p->user->processes);
183 proc_flush_task(p); 174 proc_flush_task(p);
184 write_lock_irq(&tasklist_lock); 175 write_lock_irq(&tasklist_lock);
185 ptrace_release_task(p); 176 tracehook_finish_release_task(p);
186 __exit_signal(p); 177 __exit_signal(p);
187 178
188 /* 179 /*
@@ -204,6 +195,13 @@ repeat:
204 * that case. 195 * that case.
205 */ 196 */
206 zap_leader = task_detached(leader); 197 zap_leader = task_detached(leader);
198
199 /*
200 * This maintains the invariant that release_task()
201 * only runs on a task in EXIT_DEAD, just for sanity.
202 */
203 if (zap_leader)
204 leader->exit_state = EXIT_DEAD;
207 } 205 }
208 206
209 write_unlock_irq(&tasklist_lock); 207 write_unlock_irq(&tasklist_lock);
@@ -887,7 +885,8 @@ static void forget_original_parent(struct task_struct *father)
887 */ 885 */
888static void exit_notify(struct task_struct *tsk, int group_dead) 886static void exit_notify(struct task_struct *tsk, int group_dead)
889{ 887{
890 int state; 888 int signal;
889 void *cookie;
891 890
892 /* 891 /*
893 * This does two things: 892 * This does two things:
@@ -924,22 +923,11 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
924 !capable(CAP_KILL)) 923 !capable(CAP_KILL))
925 tsk->exit_signal = SIGCHLD; 924 tsk->exit_signal = SIGCHLD;
926 925
927 /* If something other than our normal parent is ptracing us, then 926 signal = tracehook_notify_death(tsk, &cookie, group_dead);
928 * send it a SIGCHLD instead of honoring exit_signal. exit_signal 927 if (signal > 0)
929 * only has special meaning to our real parent. 928 signal = do_notify_parent(tsk, signal);
930 */
931 if (!task_detached(tsk) && thread_group_empty(tsk)) {
932 int signal = ptrace_reparented(tsk) ?
933 SIGCHLD : tsk->exit_signal;
934 do_notify_parent(tsk, signal);
935 } else if (tsk->ptrace) {
936 do_notify_parent(tsk, SIGCHLD);
937 }
938 929
939 state = EXIT_ZOMBIE; 930 tsk->exit_state = signal < 0 ? EXIT_DEAD : EXIT_ZOMBIE;
940 if (task_detached(tsk) && likely(!tsk->ptrace))
941 state = EXIT_DEAD;
942 tsk->exit_state = state;
943 931
944 /* mt-exec, de_thread() is waiting for us */ 932 /* mt-exec, de_thread() is waiting for us */
945 if (thread_group_leader(tsk) && 933 if (thread_group_leader(tsk) &&
@@ -949,8 +937,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
949 937
950 write_unlock_irq(&tasklist_lock); 938 write_unlock_irq(&tasklist_lock);
951 939
940 tracehook_report_death(tsk, signal, cookie, group_dead);
941
952 /* If the process is dead, release it - nobody will wait for it */ 942 /* If the process is dead, release it - nobody will wait for it */
953 if (state == EXIT_DEAD) 943 if (signal < 0)
954 release_task(tsk); 944 release_task(tsk);
955} 945}
956 946
@@ -1029,10 +1019,7 @@ NORET_TYPE void do_exit(long code)
1029 if (unlikely(!tsk->pid)) 1019 if (unlikely(!tsk->pid))
1030 panic("Attempted to kill the idle task!"); 1020 panic("Attempted to kill the idle task!");
1031 1021
1032 if (unlikely(current->ptrace & PT_TRACE_EXIT)) { 1022 tracehook_report_exit(&code);
1033 current->ptrace_message = code;
1034 ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
1035 }
1036 1023
1037 /* 1024 /*
1038 * We're taking recursive faults here in do_exit. Safest is to just 1025 * We're taking recursive faults here in do_exit. Safest is to just