]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
perf lock contention: Fix SIGCHLD vs pause() race in __cmd_contention()
authorSwapnil Sapkal <swapnil.sapkal@amd.com>
Wed, 20 May 2026 10:20:17 +0000 (10:20 +0000)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 20 May 2026 20:46:45 +0000 (17:46 -0300)
__cmd_contention() suffers from the same lost-wakeup race as the perf
sched stats paths: 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-lock.c

index 064b3aa4bad751468e707e1318cd295e7d512aea..94a8c35abb0bc991535ef4873463b921baf8bf62 100644 (file)
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/prctl.h>
+#include <sys/wait.h>
 #include <semaphore.h>
 #include <math.h>
 #include <limits.h>
@@ -1915,8 +1916,11 @@ out_delete:
        return err;
 }
 
+static volatile sig_atomic_t done;
+
 static void sighandler(int sig __maybe_unused)
 {
+       done = 1;
 }
 
 static int check_lock_contention_options(const struct option *options,
@@ -2054,6 +2058,7 @@ static int __cmd_contention(int argc, const char **argv)
                        goto out_delete;
                }
 
+               done = 0;
                signal(SIGINT, sighandler);
                signal(SIGCHLD, sighandler);
                signal(SIGTERM, sighandler);
@@ -2121,8 +2126,11 @@ static int __cmd_contention(int argc, const char **argv)
                if (argc)
                        evlist__start_workload(con.evlist);
 
-               /* wait for signal */
-               pause();
+               while (!done) {
+                       if (argc && waitpid(con.evlist->workload.pid, NULL, WNOHANG) > 0)
+                               break;
+                       sleep(1);
+               }
 
                lock_contention_stop();
                lock_contention_read(&con);