aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 84d13d6bb30b..1a0f10f0a4db 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1541,17 +1541,19 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
1541 if (p->exit_state == EXIT_DEAD) 1541 if (p->exit_state == EXIT_DEAD)
1542 return 0; 1542 return 0;
1543 1543
1544 if (likely(!ptrace) && unlikely(task_ptrace(p))) { 1544 /* slay zombie? */
1545 if (p->exit_state == EXIT_ZOMBIE) {
1545 /* 1546 /*
1546 * This child is hidden by ptrace. 1547 * A zombie ptracee is only visible to its ptracer.
1547 * We aren't allowed to see it now, but eventually we will. 1548 * Notification and reaping will be cascaded to the real
1549 * parent when the ptracer detaches.
1548 */ 1550 */
1549 wo->notask_error = 0; 1551 if (likely(!ptrace) && unlikely(task_ptrace(p))) {
1550 return 0; 1552 /* it will become visible, clear notask_error */
1551 } 1553 wo->notask_error = 0;
1554 return 0;
1555 }
1552 1556
1553 /* slay zombie? */
1554 if (p->exit_state == EXIT_ZOMBIE) {
1555 /* we don't reap group leaders with subthreads */ 1557 /* we don't reap group leaders with subthreads */
1556 if (!delay_group_leader(p)) 1558 if (!delay_group_leader(p))
1557 return wait_task_zombie(wo, p); 1559 return wait_task_zombie(wo, p);
@@ -1580,15 +1582,38 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
1580 wo->notask_error = 0; 1582 wo->notask_error = 0;
1581 } else { 1583 } else {
1582 /* 1584 /*
1585 * If @p is ptraced by a task in its real parent's group,
1586 * hide group stop/continued state when looking at @p as
1587 * the real parent; otherwise, a single stop can be
1588 * reported twice as group and ptrace stops.
1589 *
1590 * If a ptracer wants to distinguish the two events for its
1591 * own children, it should create a separate process which
1592 * takes the role of real parent.
1593 */
1594 if (likely(!ptrace) && task_ptrace(p) &&
1595 same_thread_group(p->parent, p->real_parent))
1596 return 0;
1597
1598 /*
1583 * @p is alive and it's gonna stop, continue or exit, so 1599 * @p is alive and it's gonna stop, continue or exit, so
1584 * there always is something to wait for. 1600 * there always is something to wait for.
1585 */ 1601 */
1586 wo->notask_error = 0; 1602 wo->notask_error = 0;
1587 } 1603 }
1588 1604
1605 /*
1606 * Wait for stopped. Depending on @ptrace, different stopped state
1607 * is used and the two don't interact with each other.
1608 */
1589 if (task_stopped_code(p, ptrace)) 1609 if (task_stopped_code(p, ptrace))
1590 return wait_task_stopped(wo, ptrace, p); 1610 return wait_task_stopped(wo, ptrace, p);
1591 1611
1612 /*
1613 * Wait for continued. There's only one continued state and the
1614 * ptracer can consume it which can confuse the real parent. Don't
1615 * use WCONTINUED from ptracer. You don't need or want it.
1616 */
1592 return wait_task_continued(wo, p); 1617 return wait_task_continued(wo, p);
1593} 1618}
1594 1619