Skip to content

Commit 0b7747a

Browse files
oleg-nesterovbrauner
authored andcommitted
pidfs: cleanup the usage of do_notify_pidfd()
If a single-threaded process exits do_notify_pidfd() will be called twice, from exit_notify() and right after that from do_notify_parent(). 1. Change exit_notify() to call do_notify_pidfd() if the exiting task is not ptraced and it is not a group leader. 2. Change do_notify_parent() to call do_notify_pidfd() unconditionally. If tsk is not ptraced, do_notify_parent() will only be called when it is a group-leader and thread_group_empty() is true. This means that if tsk is ptraced, do_notify_pidfd() will be called from do_notify_parent() even if tsk is a delay_group_leader(). But this case is less common, and apart from the unnecessary __wake_up() is harmless. Granted, this unnecessary __wake_up() can be avoided, but I don't want to do it in this patch because it's just a consequence of another historical oddity: we notify the tracer even if !thread_group_empty(), but do_wait() from debugger can't work until all other threads exit. With or without this patch we should either eliminate do_notify_parent() in this case, or change do_wait(WEXITED) to untrace the ptraced delay_group_leader() at least when ptrace_reparented(). Signed-off-by: Oleg Nesterov <oleg@redhat.com> Link: https://lore.kernel.org/r/20250323171955.GA834@redhat.com Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 2df0c02 commit 0b7747a

File tree

2 files changed

+5
-11
lines changed

2 files changed

+5
-11
lines changed

kernel/exit.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -756,12 +756,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
756756
kill_orphaned_pgrp(tsk->group_leader, NULL);
757757

758758
tsk->exit_state = EXIT_ZOMBIE;
759-
/*
760-
* Ignore thread-group leaders that exited before all
761-
* subthreads did.
762-
*/
763-
if (!delay_group_leader(tsk))
764-
do_notify_pidfd(tsk);
765759

766760
if (unlikely(tsk->ptrace)) {
767761
int sig = thread_group_leader(tsk) &&
@@ -774,6 +768,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
774768
do_notify_parent(tsk, tsk->exit_signal);
775769
} else {
776770
autoreap = true;
771+
/* untraced sub-thread */
772+
do_notify_pidfd(tsk);
777773
}
778774

779775
if (autoreap) {

kernel/signal.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,11 +2179,9 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
21792179

21802180
WARN_ON_ONCE(!tsk->ptrace &&
21812181
(tsk->group_leader != tsk || !thread_group_empty(tsk)));
2182-
/*
2183-
* Notify for thread-group leaders without subthreads.
2184-
*/
2185-
if (thread_group_empty(tsk))
2186-
do_notify_pidfd(tsk);
2182+
2183+
/* ptraced, or group-leader without sub-threads */
2184+
do_notify_pidfd(tsk);
21872185

21882186
if (sig != SIGCHLD) {
21892187
/*

0 commit comments

Comments
 (0)