diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 18:06:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 18:06:50 -0400 |
commit | 8209f53d79444747782a28520187abaf689761f2 (patch) | |
tree | 726270ea29e037f026d77a99787b9d844531ac42 /kernel/exit.c | |
parent | 22a3b9771117d566def0150ea787fcc95f16e724 (diff) | |
parent | eac1b5e57d7abc836e78fd3fbcf77dbeed01edc9 (diff) |
Merge branch 'ptrace' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg/misc
* 'ptrace' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg/misc: (39 commits)
ptrace: do_wait(traced_leader_killed_by_mt_exec) can block forever
ptrace: fix ptrace_signal() && STOP_DEQUEUED interaction
connector: add an event for monitoring process tracers
ptrace: dont send SIGSTOP on auto-attach if PT_SEIZED
ptrace: mv send-SIGSTOP from do_fork() to ptrace_init_task()
ptrace_init_task: initialize child->jobctl explicitly
has_stopped_jobs: s/task_is_stopped/SIGNAL_STOP_STOPPED/
ptrace: make former thread ID available via PTRACE_GETEVENTMSG after PTRACE_EVENT_EXEC stop
ptrace: wait_consider_task: s/same_thread_group/ptrace_reparented/
ptrace: kill real_parent_is_ptracer() in in favor of ptrace_reparented()
ptrace: ptrace_reparented() should check same_thread_group()
redefine thread_group_leader() as exit_signal >= 0
do not change dead_task->exit_signal
kill task_detached()
reparent_leader: check EXIT_DEAD instead of task_detached()
make do_notify_parent() __must_check, update the callers
__ptrace_detach: avoid task_detached(), check do_notify_parent()
kill tracehook_notify_death()
make do_notify_parent() return bool
ptrace: s/tracehook_tracer_task()/ptrace_parent()/
...
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 91 |
1 files changed, 40 insertions, 51 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index f2b321bae440..73bb192a3d32 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -169,7 +169,6 @@ void release_task(struct task_struct * p) | |||
169 | struct task_struct *leader; | 169 | struct task_struct *leader; |
170 | int zap_leader; | 170 | int zap_leader; |
171 | repeat: | 171 | repeat: |
172 | tracehook_prepare_release_task(p); | ||
173 | /* don't need to get the RCU readlock here - the process is dead and | 172 | /* don't need to get the RCU readlock here - the process is dead and |
174 | * can't be modifying its own credentials. But shut RCU-lockdep up */ | 173 | * can't be modifying its own credentials. But shut RCU-lockdep up */ |
175 | rcu_read_lock(); | 174 | rcu_read_lock(); |
@@ -179,7 +178,7 @@ repeat: | |||
179 | proc_flush_task(p); | 178 | proc_flush_task(p); |
180 | 179 | ||
181 | write_lock_irq(&tasklist_lock); | 180 | write_lock_irq(&tasklist_lock); |
182 | tracehook_finish_release_task(p); | 181 | ptrace_release_task(p); |
183 | __exit_signal(p); | 182 | __exit_signal(p); |
184 | 183 | ||
185 | /* | 184 | /* |
@@ -190,22 +189,12 @@ repeat: | |||
190 | zap_leader = 0; | 189 | zap_leader = 0; |
191 | leader = p->group_leader; | 190 | leader = p->group_leader; |
192 | if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) { | 191 | if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) { |
193 | BUG_ON(task_detached(leader)); | ||
194 | do_notify_parent(leader, leader->exit_signal); | ||
195 | /* | 192 | /* |
196 | * If we were the last child thread and the leader has | 193 | * If we were the last child thread and the leader has |
197 | * exited already, and the leader's parent ignores SIGCHLD, | 194 | * exited already, and the leader's parent ignores SIGCHLD, |
198 | * then we are the one who should release the leader. | 195 | * then we are the one who should release the leader. |
199 | * | ||
200 | * do_notify_parent() will have marked it self-reaping in | ||
201 | * that case. | ||
202 | */ | ||
203 | zap_leader = task_detached(leader); | ||
204 | |||
205 | /* | ||
206 | * This maintains the invariant that release_task() | ||
207 | * only runs on a task in EXIT_DEAD, just for sanity. | ||
208 | */ | 196 | */ |
197 | zap_leader = do_notify_parent(leader, leader->exit_signal); | ||
209 | if (zap_leader) | 198 | if (zap_leader) |
210 | leader->exit_state = EXIT_DEAD; | 199 | leader->exit_state = EXIT_DEAD; |
211 | } | 200 | } |
@@ -277,18 +266,16 @@ int is_current_pgrp_orphaned(void) | |||
277 | return retval; | 266 | return retval; |
278 | } | 267 | } |
279 | 268 | ||
280 | static int has_stopped_jobs(struct pid *pgrp) | 269 | static bool has_stopped_jobs(struct pid *pgrp) |
281 | { | 270 | { |
282 | int retval = 0; | ||
283 | struct task_struct *p; | 271 | struct task_struct *p; |
284 | 272 | ||
285 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { | 273 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { |
286 | if (!task_is_stopped(p)) | 274 | if (p->signal->flags & SIGNAL_STOP_STOPPED) |
287 | continue; | 275 | return true; |
288 | retval = 1; | ||
289 | break; | ||
290 | } while_each_pid_task(pgrp, PIDTYPE_PGID, p); | 276 | } while_each_pid_task(pgrp, PIDTYPE_PGID, p); |
291 | return retval; | 277 | |
278 | return false; | ||
292 | } | 279 | } |
293 | 280 | ||
294 | /* | 281 | /* |
@@ -751,7 +738,7 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p, | |||
751 | { | 738 | { |
752 | list_move_tail(&p->sibling, &p->real_parent->children); | 739 | list_move_tail(&p->sibling, &p->real_parent->children); |
753 | 740 | ||
754 | if (task_detached(p)) | 741 | if (p->exit_state == EXIT_DEAD) |
755 | return; | 742 | return; |
756 | /* | 743 | /* |
757 | * If this is a threaded reparent there is no need to | 744 | * If this is a threaded reparent there is no need to |
@@ -764,10 +751,9 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p, | |||
764 | p->exit_signal = SIGCHLD; | 751 | p->exit_signal = SIGCHLD; |
765 | 752 | ||
766 | /* If it has exited notify the new parent about this child's death. */ | 753 | /* If it has exited notify the new parent about this child's death. */ |
767 | if (!task_ptrace(p) && | 754 | if (!p->ptrace && |
768 | p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) { | 755 | p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) { |
769 | do_notify_parent(p, p->exit_signal); | 756 | if (do_notify_parent(p, p->exit_signal)) { |
770 | if (task_detached(p)) { | ||
771 | p->exit_state = EXIT_DEAD; | 757 | p->exit_state = EXIT_DEAD; |
772 | list_move_tail(&p->sibling, dead); | 758 | list_move_tail(&p->sibling, dead); |
773 | } | 759 | } |
@@ -794,7 +780,7 @@ static void forget_original_parent(struct task_struct *father) | |||
794 | do { | 780 | do { |
795 | t->real_parent = reaper; | 781 | t->real_parent = reaper; |
796 | if (t->parent == father) { | 782 | if (t->parent == father) { |
797 | BUG_ON(task_ptrace(t)); | 783 | BUG_ON(t->ptrace); |
798 | t->parent = t->real_parent; | 784 | t->parent = t->real_parent; |
799 | } | 785 | } |
800 | if (t->pdeath_signal) | 786 | if (t->pdeath_signal) |
@@ -819,8 +805,7 @@ static void forget_original_parent(struct task_struct *father) | |||
819 | */ | 805 | */ |
820 | static void exit_notify(struct task_struct *tsk, int group_dead) | 806 | static void exit_notify(struct task_struct *tsk, int group_dead) |
821 | { | 807 | { |
822 | int signal; | 808 | bool autoreap; |
823 | void *cookie; | ||
824 | 809 | ||
825 | /* | 810 | /* |
826 | * This does two things: | 811 | * This does two things: |
@@ -851,26 +836,33 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
851 | * we have changed execution domain as these two values started | 836 | * we have changed execution domain as these two values started |
852 | * the same after a fork. | 837 | * the same after a fork. |
853 | */ | 838 | */ |
854 | if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) && | 839 | if (thread_group_leader(tsk) && tsk->exit_signal != SIGCHLD && |
855 | (tsk->parent_exec_id != tsk->real_parent->self_exec_id || | 840 | (tsk->parent_exec_id != tsk->real_parent->self_exec_id || |
856 | tsk->self_exec_id != tsk->parent_exec_id)) | 841 | tsk->self_exec_id != tsk->parent_exec_id)) |
857 | tsk->exit_signal = SIGCHLD; | 842 | tsk->exit_signal = SIGCHLD; |
858 | 843 | ||
859 | signal = tracehook_notify_death(tsk, &cookie, group_dead); | 844 | if (unlikely(tsk->ptrace)) { |
860 | if (signal >= 0) | 845 | int sig = thread_group_leader(tsk) && |
861 | signal = do_notify_parent(tsk, signal); | 846 | thread_group_empty(tsk) && |
847 | !ptrace_reparented(tsk) ? | ||
848 | tsk->exit_signal : SIGCHLD; | ||
849 | autoreap = do_notify_parent(tsk, sig); | ||
850 | } else if (thread_group_leader(tsk)) { | ||
851 | autoreap = thread_group_empty(tsk) && | ||
852 | do_notify_parent(tsk, tsk->exit_signal); | ||
853 | } else { | ||
854 | autoreap = true; | ||
855 | } | ||
862 | 856 | ||
863 | tsk->exit_state = signal == DEATH_REAP ? EXIT_DEAD : EXIT_ZOMBIE; | 857 | tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE; |
864 | 858 | ||
865 | /* mt-exec, de_thread() is waiting for group leader */ | 859 | /* mt-exec, de_thread() is waiting for group leader */ |
866 | if (unlikely(tsk->signal->notify_count < 0)) | 860 | if (unlikely(tsk->signal->notify_count < 0)) |
867 | wake_up_process(tsk->signal->group_exit_task); | 861 | wake_up_process(tsk->signal->group_exit_task); |
868 | write_unlock_irq(&tasklist_lock); | 862 | write_unlock_irq(&tasklist_lock); |
869 | 863 | ||
870 | tracehook_report_death(tsk, signal, cookie, group_dead); | ||
871 | |||
872 | /* If the process is dead, release it - nobody will wait for it */ | 864 | /* If the process is dead, release it - nobody will wait for it */ |
873 | if (signal == DEATH_REAP) | 865 | if (autoreap) |
874 | release_task(tsk); | 866 | release_task(tsk); |
875 | } | 867 | } |
876 | 868 | ||
@@ -923,7 +915,7 @@ NORET_TYPE void do_exit(long code) | |||
923 | */ | 915 | */ |
924 | set_fs(USER_DS); | 916 | set_fs(USER_DS); |
925 | 917 | ||
926 | tracehook_report_exit(&code); | 918 | ptrace_event(PTRACE_EVENT_EXIT, code); |
927 | 919 | ||
928 | validate_creds_for_do_exit(tsk); | 920 | validate_creds_for_do_exit(tsk); |
929 | 921 | ||
@@ -1235,9 +1227,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1235 | traced = ptrace_reparented(p); | 1227 | traced = ptrace_reparented(p); |
1236 | /* | 1228 | /* |
1237 | * It can be ptraced but not reparented, check | 1229 | * It can be ptraced but not reparented, check |
1238 | * !task_detached() to filter out sub-threads. | 1230 | * thread_group_leader() to filter out sub-threads. |
1239 | */ | 1231 | */ |
1240 | if (likely(!traced) && likely(!task_detached(p))) { | 1232 | if (likely(!traced) && thread_group_leader(p)) { |
1241 | struct signal_struct *psig; | 1233 | struct signal_struct *psig; |
1242 | struct signal_struct *sig; | 1234 | struct signal_struct *sig; |
1243 | unsigned long maxrss; | 1235 | unsigned long maxrss; |
@@ -1345,16 +1337,13 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1345 | /* We dropped tasklist, ptracer could die and untrace */ | 1337 | /* We dropped tasklist, ptracer could die and untrace */ |
1346 | ptrace_unlink(p); | 1338 | ptrace_unlink(p); |
1347 | /* | 1339 | /* |
1348 | * If this is not a detached task, notify the parent. | 1340 | * If this is not a sub-thread, notify the parent. |
1349 | * If it's still not detached after that, don't release | 1341 | * If parent wants a zombie, don't release it now. |
1350 | * it now. | ||
1351 | */ | 1342 | */ |
1352 | if (!task_detached(p)) { | 1343 | if (thread_group_leader(p) && |
1353 | do_notify_parent(p, p->exit_signal); | 1344 | !do_notify_parent(p, p->exit_signal)) { |
1354 | if (!task_detached(p)) { | 1345 | p->exit_state = EXIT_ZOMBIE; |
1355 | p->exit_state = EXIT_ZOMBIE; | 1346 | p = NULL; |
1356 | p = NULL; | ||
1357 | } | ||
1358 | } | 1347 | } |
1359 | write_unlock_irq(&tasklist_lock); | 1348 | write_unlock_irq(&tasklist_lock); |
1360 | } | 1349 | } |
@@ -1367,7 +1356,8 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1367 | static int *task_stopped_code(struct task_struct *p, bool ptrace) | 1356 | static int *task_stopped_code(struct task_struct *p, bool ptrace) |
1368 | { | 1357 | { |
1369 | if (ptrace) { | 1358 | if (ptrace) { |
1370 | if (task_is_stopped_or_traced(p)) | 1359 | if (task_is_stopped_or_traced(p) && |
1360 | !(p->jobctl & JOBCTL_LISTENING)) | ||
1371 | return &p->exit_code; | 1361 | return &p->exit_code; |
1372 | } else { | 1362 | } else { |
1373 | if (p->signal->flags & SIGNAL_STOP_STOPPED) | 1363 | if (p->signal->flags & SIGNAL_STOP_STOPPED) |
@@ -1563,7 +1553,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace, | |||
1563 | * Notification and reaping will be cascaded to the real | 1553 | * Notification and reaping will be cascaded to the real |
1564 | * parent when the ptracer detaches. | 1554 | * parent when the ptracer detaches. |
1565 | */ | 1555 | */ |
1566 | if (likely(!ptrace) && unlikely(task_ptrace(p))) { | 1556 | if (likely(!ptrace) && unlikely(p->ptrace)) { |
1567 | /* it will become visible, clear notask_error */ | 1557 | /* it will become visible, clear notask_error */ |
1568 | wo->notask_error = 0; | 1558 | wo->notask_error = 0; |
1569 | return 0; | 1559 | return 0; |
@@ -1606,8 +1596,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace, | |||
1606 | * own children, it should create a separate process which | 1596 | * own children, it should create a separate process which |
1607 | * takes the role of real parent. | 1597 | * takes the role of real parent. |
1608 | */ | 1598 | */ |
1609 | if (likely(!ptrace) && task_ptrace(p) && | 1599 | if (likely(!ptrace) && p->ptrace && !ptrace_reparented(p)) |
1610 | same_thread_group(p->parent, p->real_parent)) | ||
1611 | return 0; | 1600 | return 0; |
1612 | 1601 | ||
1613 | /* | 1602 | /* |