Add a test to check the registration after fork
authorMichael Jeanson <mjeanson@efficios.com>
Mon, 29 Jul 2024 18:10:46 +0000 (18:10 +0000)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 30 Jul 2024 18:22:43 +0000 (14:22 -0400)
Change-Id: I5a8321945edbc1bb00122a5809cecd4be6c7de20
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
.gitignore
tests/Makefile.am
tests/fork_test.c [new file with mode: 0644]
tests/fork_test_cxx.cpp [new file with mode: 0644]
tests/run_fork_test.tap [new file with mode: 0755]
tests/run_fork_test_cxx.tap [new file with mode: 0755]
tests/utils/tap.c
tests/utils/tap.h

index 47ca9cc6fcc4d69ea3d08c0e203653f792e7930b..19cb495de89236e58a3fefaeca4db0a7345100b3 100644 (file)
@@ -62,6 +62,8 @@ dkms.conf
 /tests/basic_percpu_ops_mm_cid_test_cxx.tap
 /tests/basic_test.tap
 /tests/basic_test_cxx.tap
+/tests/fork_test.tap
+/tests/fork_test_cxx.tap
 /tests/mempool_cow_race_test.tap
 /tests/mempool_cow_race_test_cxx.tap
 /tests/mempool_test.tap
index d7f8ea56dd7236d32c6bf1f0d2de3daf21ebaef4..d4df4951c56db0d89e0067adafc6e79d6dca9be3 100644 (file)
@@ -19,6 +19,8 @@ noinst_PROGRAMS = \
        basic_percpu_ops_mm_cid_test_cxx.tap \
        basic_test.tap \
        basic_test_cxx.tap \
+       fork_test.tap \
+       fork_test_cxx.tap \
        mempool_test.tap \
        mempool_test_cxx.tap \
        mempool_cow_race_test.tap \
@@ -43,6 +45,8 @@ noinst_PROGRAMS = \
        unregistered_test.tap
 
 dist_noinst_SCRIPTS = \
+       run_fork_test_cxx.tap \
+       run_fork_test.tap \
        run_no_syscall_test_cxx.tap \
        run_no_syscall_test.tap \
        run_param_test_cxx.tap \
@@ -100,6 +104,12 @@ basic_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/util
 basic_test_cxx_tap_SOURCES = basic_test_cxx.cpp
 basic_test_cxx_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
 
+fork_test_tap_SOURCES = fork_test.c
+fork_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
+fork_test_cxx_tap_SOURCES = fork_test_cxx.cpp
+fork_test_cxx_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
 mempool_test_tap_SOURCES = mempool_test.c
 mempool_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
 
@@ -162,6 +172,8 @@ param_test_mm_cid_compare_twice_cxx_LDADD = $(top_builddir)/src/librseq.la $(DL_
 TESTS = \
        basic_test.tap \
        basic_test_cxx.tap \
+       run_fork_test.tap \
+       run_fork_test_cxx.tap \
        run_unregistered_test.tap \
        run_unregistered_test_cxx.tap \
        run_syscall_errors_test.tap \
diff --git a/tests/fork_test.c b/tests/fork_test.c
new file mode 100644 (file)
index 0000000..050168a
--- /dev/null
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <syscall.h>
+#include <unistd.h>
+
+#include <rseq/rseq.h>
+
+#include "tap.h"
+
+#define NR_TESTS 4
+
+/*
+ * Check that a registration from a parent is still active in the child.
+ */
+
+static int sys_rseq(void *rseq_abi, uint32_t rseq_len,
+                   int flags, uint32_t sig)
+{
+       return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
+}
+
+static
+int test_child(void)
+{
+       int ret, errno_copy;
+       struct rseq_abi *global_rseq = rseq_get_abi();
+
+       /* The registration from the parent should survive in the child. */
+
+       ret = sys_rseq(global_rseq, 32, 0, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EBUSY, "Registration is still active in the child");
+
+       ok((int32_t) global_rseq->cpu_id >= 0,
+                       "rseq->cpu_id after registration is 0 or greater (%d)",
+                       (int32_t) global_rseq->cpu_id);
+
+       return exit_status();
+}
+
+int main(void)
+{
+       pid_t pid;
+       int ret, wstatus;
+       struct rseq_abi *global_rseq = rseq_get_abi();
+
+       /*
+        * Skip all tests if the rseq syscall is unavailable
+        */
+       if (!rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
+               plan_skip_all("The rseq syscall is unavailable");
+       }
+
+       plan_tests(NR_TESTS);
+
+       ret = rseq_register_current_thread();
+       ok(ret == 0, "Registered rseq in the parent");
+
+       ok((int32_t) global_rseq->cpu_id >= 0,
+                       "rseq->cpu_id after registration is 0 or greater (%d)",
+                       (int32_t) global_rseq->cpu_id);
+
+       pid = fork();
+       switch (pid) {
+       case -1:
+               perror("fork");
+               ret = EXIT_FAILURE;
+               break;
+       case 0:
+               /* Child */
+               ret = test_child();
+               break;
+       default:
+               /* Parent */
+               ret = waitpid(pid, &wstatus, 0);
+               if (ret < 0) {
+                       ret = EXIT_FAILURE;
+               } else {
+                       /* Let the child handle the tap cleanup. */
+                       disable_cleanup();
+
+                       ret = WEXITSTATUS(wstatus);
+               }
+               break;
+       }
+
+       return ret;
+}
diff --git a/tests/fork_test_cxx.cpp b/tests/fork_test_cxx.cpp
new file mode 100644 (file)
index 0000000..7226930
--- /dev/null
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 EfficiOS Inc.
+
+#include "fork_test.c"
diff --git a/tests/run_fork_test.tap b/tests/run_fork_test.tap
new file mode 100755 (executable)
index 0000000..af281d7
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+SH_TAP=0
+
+if [ "x${RSEQ_TESTS_SRCDIR:-}" != "x" ]; then
+       UTILSSH="$RSEQ_TESTS_SRCDIR/utils/utils.sh"
+else
+       UTILSSH="$(dirname "$0")/utils/utils.sh"
+fi
+
+# shellcheck source=./utils/utils.sh
+source "$UTILSSH"
+
+GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0" "${RSEQ_TESTS_BUILDDIR}/fork_test.tap"
diff --git a/tests/run_fork_test_cxx.tap b/tests/run_fork_test_cxx.tap
new file mode 100755 (executable)
index 0000000..2f7ec99
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+SH_TAP=0
+
+if [ "x${RSEQ_TESTS_SRCDIR:-}" != "x" ]; then
+       UTILSSH="$RSEQ_TESTS_SRCDIR/utils/utils.sh"
+else
+       UTILSSH="$(dirname "$0")/utils/utils.sh"
+fi
+
+# shellcheck source=./utils/utils.sh
+source "$UTILSSH"
+
+GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0" "${RSEQ_TESTS_BUILDDIR}/fork_test_cxx.tap"
index 9f41408bd4c4dd25a729b607b4c276bb115ab27b..1d3b6703df836ec3280ca405b59db2fb20419374 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "tap.h"
 
+static int no_cleanup = 0;
 static int no_plan = 0;
 static int skip_all = 0;
 static int have_plan = 0;
@@ -396,6 +397,16 @@ exit_status(void)
        return r;
 }
 
+void
+disable_cleanup(void)
+{
+       LOCK;
+
+       no_cleanup = 1;
+
+       UNLOCK;
+}
+
 /*
  * Cleanup at the end of the run, produce any final output that might be
  * required.
@@ -406,6 +417,11 @@ _cleanup(void)
 
        LOCK;
 
+       if(no_cleanup) {
+               UNLOCK;
+               return;
+       }
+
        /* If plan_no_plan() wasn't called, and we don't have a plan,
           and we're not skipping everything, then something happened
           before we could produce any output */
index b527b317f384f44acb87b6ff697bee66613ca5e7..2a91cbad67691637bc53723fa994071f04266958 100644 (file)
@@ -85,6 +85,8 @@ void todo_end(void);
 
 int exit_status(void);
 
+void disable_cleanup(void);
+
 #ifdef __cplusplus
 }
 #endif
This page took 0.027806 seconds and 4 git commands to generate.