aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-07-25 22:45:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 15:00:09 -0400
commit2b2a1ff64afbadac842bbc58c5166962cf4f7664 (patch)
tree660640eb95117ce6f7436331f23f73805abced10 /kernel
parentfa00b80b3c41a845b3d56f866fb40a2e98754c51 (diff)
tracehook: death
This moves the ptrace logic in task death (exit_notify) into tracehook.h inlines. Some code is rearranged slightly to make things nicer. There is no change, only cleanup. There is one hook called with the tasklist_lock write-locked, as ptrace needs. There is also a new hook called after exit_state changes and without locks. This is a better place for tracing work to be in the future, since it doesn't delay the whole system with locking. Signed-off-by: Roland McGrath <roland@redhat.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Reviewed-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c26
-rw-r--r--kernel/signal.c10
2 files changed, 16 insertions, 20 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index da28745f7c38..6cdf60712bd2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -885,7 +885,8 @@ static void forget_original_parent(struct task_struct *father)
885 */ 885 */
886static void exit_notify(struct task_struct *tsk, int group_dead) 886static void exit_notify(struct task_struct *tsk, int group_dead)
887{ 887{
888 int state; 888 int signal;
889 void *cookie;
889 890
890 /* 891 /*
891 * This does two things: 892 * This does two things:
@@ -922,22 +923,11 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
922 !capable(CAP_KILL)) 923 !capable(CAP_KILL))
923 tsk->exit_signal = SIGCHLD; 924 tsk->exit_signal = SIGCHLD;
924 925
925 /* If something other than our normal parent is ptracing us, then 926 signal = tracehook_notify_death(tsk, &cookie, group_dead);
926 * send it a SIGCHLD instead of honoring exit_signal. exit_signal 927 if (signal > 0)
927 * only has special meaning to our real parent. 928 signal = do_notify_parent(tsk, signal);
928 */
929 if (!task_detached(tsk) && thread_group_empty(tsk)) {
930 int signal = ptrace_reparented(tsk) ?
931 SIGCHLD : tsk->exit_signal;
932 do_notify_parent(tsk, signal);
933 } else if (tsk->ptrace) {
934 do_notify_parent(tsk, SIGCHLD);
935 }
936 929
937 state = EXIT_ZOMBIE; 930 tsk->exit_state = signal < 0 ? EXIT_DEAD : EXIT_ZOMBIE;
938 if (task_detached(tsk) && likely(!tsk->ptrace))
939 state = EXIT_DEAD;
940 tsk->exit_state = state;
941 931
942 /* mt-exec, de_thread() is waiting for us */ 932 /* mt-exec, de_thread() is waiting for us */
943 if (thread_group_leader(tsk) && 933 if (thread_group_leader(tsk) &&
@@ -947,8 +937,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
947 937
948 write_unlock_irq(&tasklist_lock); 938 write_unlock_irq(&tasklist_lock);
949 939
940 tracehook_report_death(tsk, signal, cookie, group_dead);
941
950 /* 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 */
951 if (state == EXIT_DEAD) 943 if (signal < 0)
952 release_task(tsk); 944 release_task(tsk);
953} 945}
954 946
diff --git a/kernel/signal.c b/kernel/signal.c
index e9e699f4b1bd..0e862d3130ff 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1326,9 +1326,11 @@ static inline void __wake_up_parent(struct task_struct *p,
1326/* 1326/*
1327 * Let a parent know about the death of a child. 1327 * Let a parent know about the death of a child.
1328 * For a stopped/continued status change, use do_notify_parent_cldstop instead. 1328 * For a stopped/continued status change, use do_notify_parent_cldstop instead.
1329 *
1330 * Returns -1 if our parent ignored us and so we've switched to
1331 * self-reaping, or else @sig.
1329 */ 1332 */
1330 1333int do_notify_parent(struct task_struct *tsk, int sig)
1331void do_notify_parent(struct task_struct *tsk, int sig)
1332{ 1334{
1333 struct siginfo info; 1335 struct siginfo info;
1334 unsigned long flags; 1336 unsigned long flags;
@@ -1399,12 +1401,14 @@ void do_notify_parent(struct task_struct *tsk, int sig)
1399 */ 1401 */
1400 tsk->exit_signal = -1; 1402 tsk->exit_signal = -1;
1401 if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) 1403 if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
1402 sig = 0; 1404 sig = -1;
1403 } 1405 }
1404 if (valid_signal(sig) && sig > 0) 1406 if (valid_signal(sig) && sig > 0)
1405 __group_send_sig_info(sig, &info, tsk->parent); 1407 __group_send_sig_info(sig, &info, tsk->parent);
1406 __wake_up_parent(tsk, tsk->parent); 1408 __wake_up_parent(tsk, tsk->parent);
1407 spin_unlock_irqrestore(&psig->siglock, flags); 1409 spin_unlock_irqrestore(&psig->siglock, flags);
1410
1411 return sig;
1408} 1412}
1409 1413
1410static void do_notify_parent_cldstop(struct task_struct *tsk, int why) 1414static void do_notify_parent_cldstop(struct task_struct *tsk, int why)