Re: [PATCH 0/3] perf: Fix SIGCHLD vs pause() race with short-lived workloads

James Clark
2026-04-01T10:55:36Z

On 01/04/2026 7:41 am, Swapnil Sapkal wrote:
> Some perf subcommands (sched stats, lock contention) use the pattern
> of forking a workload child, calling evlist__start_workload() to uncork
> it, and then calling pause() to wait for a signal (typically SIGCHLD
> when the child exits, or SIGINT/SIGTERM from the user).
>
> This pattern has a race condition: if the workload is very short-lived,
> the child can exit and deliver SIGCHLD in the window between
> evlist__start_workload() and pause(). Since pause() only returns when a
> signal is received *while the process is suspended*, and SIGCHLD has
> already been delivered and handled by the empty sighandler(), pause()
> blocks indefinitely.
>
> The fix uses the standard POSIX pattern for this class of bug:
>
> 1. Block SIGCHLD (via sigprocmask) before starting the workload.
> If the child exits, the signal remains pending rather than being
> delivered and lost.
>
> 2. Replace pause() with sigsuspend(&oldmask), which atomically
> unblocks SIGCHLD and suspends the process. There is no window
> where the signal can slip through unnoticed.
>
> 3. Restore the original signal mask after sigsuspend() returns.
>
> SIGINT and SIGTERM are not blocked at any point, so Ctrl+C and
> graceful termination continue to work exactly as before.
>
> Three call sites are affected across two files:
> - perf_sched__schedstat_record() in builtin-sched.c
> - perf_sched__schedstat_live() in builtin-sched.c
> - __cmd_contention() in builtin-lock.c
>
> The two pause() sites in builtin-kwork.c are NOT affected because they
> do not register SIGCHLD or fork workload children; they only wait for
> user-initiated SIGINT/SIGTERM.
>
> Swapnil Sapkal (3):
> perf sched stats: Fix SIGCHLD race in schedstat_record()
> perf sched stats: Fix SIGCHLD race in schedstat_live()
> perf lock contention: Fix SIGCHLD race in __cmd_contention()
>
> tools/perf/builtin-lock.c | 20 ++++++++++++++++++--
> tools/perf/builtin-sched.c | 30 ++++++++++++++++++++++++++----
> 2 files changed, 44 insertions(+), 6 deletions(-)
>

Reviewed-by: James Clark <james.clark@linaro.org>