perf test: Add a signal handler to kill forked child processes
authorIan Rogers <irogers@google.com>
Fri, 25 Oct 2024 19:21:08 +0000 (12:21 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 28 Oct 2024 16:32:58 +0000 (09:32 -0700)
If the `perf test` process is killed the child tests continue running
and may run indefinitely. Propagate SIGINT (ctrl-C) and SIGTERM (kill)
signals to the running child processes so that they terminate when the
parent is killed.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Ilya Leoshkevich <iii@linux.ibm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Veronika Molnarova <vmolnaro@redhat.com>
Link: https://lore.kernel.org/r/20241025192109.132482-10-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/tests/builtin-test.c

index a0a678facc458d6f42d9870737a43b6d81c0d139..2f880f48cdc56a700bc4e4caeb62f89b9c5d053e 100644 (file)
@@ -472,13 +472,22 @@ static int start_test(struct test_suite *test, int i, int subi, struct child_tes
        for (j = 0, k = 0; j < ARRAY_SIZE(tests); j++, k = 0)   \
                while ((t = tests[j][k++]) != NULL)
 
+/* State outside of __cmd_test for the sake of the signal handler. */
+
+static size_t num_tests;
+static struct child_test **child_tests;
+static jmp_buf cmd_test_jmp_buf;
+
+static void cmd_test_sig_handler(int sig)
+{
+       siglongjmp(cmd_test_jmp_buf, sig);
+}
+
 static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
 {
        struct test_suite *t;
-       int width = 0;
+       static int width = 0;
        unsigned int j, k;
-       size_t num_tests = 0;
-       struct child_test **child_tests;
        int err = 0;
 
        for_each_test(j, k, t) {
@@ -502,6 +511,26 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
        if (!child_tests)
                return -ENOMEM;
 
+       err = sigsetjmp(cmd_test_jmp_buf, 1);
+       if (err) {
+               pr_err("\nSignal (%d) while running tests.\nTerminating tests with the same signal\n",
+                      err);
+               for (size_t x = 0; x < num_tests; x++) {
+                       struct child_test *child_test = child_tests[x];
+
+                       if (!child_test)
+                               continue;
+
+                       pr_debug3("Killing %d pid %d\n",
+                                 child_test->test_num + 1,
+                                 child_test->process.pid);
+                       kill(child_test->process.pid, err);
+               }
+               goto err_out;
+       }
+       signal(SIGINT, cmd_test_sig_handler);
+       signal(SIGTERM, cmd_test_sig_handler);
+
        /*
         * In parallel mode pass 1 runs non-exclusive tests in parallel, pass 2
         * runs the exclusive tests sequentially. In other modes all tests are
@@ -562,6 +591,8 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
                }
        }
 err_out:
+       signal(SIGINT, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
        if (err) {
                pr_err("Internal test harness failure. Completing any started tests:\n:");
                for (size_t x = 0; x < num_tests; x++)