]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf sched stats: Fix SIGCHLD vs pause() race in schedstat_live()
authorSwapnil Sapkal <swapnil.sapkal@amd.com>
Wed, 20 May 2026 10:20:16 +0000 (10:20 +0000)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 20 May 2026 20:46:45 +0000 (17:46 -0300)
perf_sched__schedstat_live() has the same lost-wakeup race as
perf_sched__schedstat_record(): a short-lived workload's SIGCHLD
can be consumed by the signal handler before pause() is entered,
hanging the process.

Apply the same fix: replace pause() with a loop checking the 'done'
flag and using waitpid(WNOHANG) for the workload case.

Suggested-by: Namhyung Kim <namhyung@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Swapnil Sapkal <swapnil.sapkal@amd.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-sched.c

index 4f54a08e66728ee9cb9006e9d0ca039df472cd0c..812a1b0d56d6e5f3f51379f3f4072de38b1ddd5e 100644 (file)
@@ -4743,6 +4743,7 @@ static int perf_sched__schedstat_live(struct perf_sched *sched,
        int reset = 0;
        int err = 0;
 
+       done = 0;
        signal(SIGINT, sighandler);
        signal(SIGCHLD, sighandler);
        signal(SIGTERM, sighandler);
@@ -4788,8 +4789,11 @@ static int perf_sched__schedstat_live(struct perf_sched *sched,
        if (argc)
                evlist__start_workload(evlist);
 
-       /* wait for signal */
-       pause();
+       while (!done) {
+               if (argc && waitpid(evlist->workload.pid, NULL, WNOHANG) > 0)
+                       break;
+               sleep(1);
+       }
 
        if (reset) {
                err = disable_sched_schedstat();