diff options
| author | Roland McGrath <roland@redhat.com> | 2008-07-25 22:45:54 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 15:00:09 -0400 |
| commit | 2b2a1ff64afbadac842bbc58c5166962cf4f7664 (patch) | |
| tree | 660640eb95117ce6f7436331f23f73805abced10 /kernel | |
| parent | fa00b80b3c41a845b3d56f866fb40a2e98754c51 (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.c | 26 | ||||
| -rw-r--r-- | kernel/signal.c | 10 |
2 files changed, 16 insertions, 20 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index da28745f7c3..6cdf60712bd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -885,7 +885,8 @@ static void forget_original_parent(struct task_struct *father) | |||
| 885 | */ | 885 | */ |
| 886 | static void exit_notify(struct task_struct *tsk, int group_dead) | 886 | static 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 e9e699f4b1b..0e862d3130f 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 | 1333 | int do_notify_parent(struct task_struct *tsk, int sig) | |
| 1331 | void 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 | ||
| 1410 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why) | 1414 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why) |
