diff mbox series

[v4,2/4] futex_wait07: Add EINTR error coverage test

Message ID 20260507111809.28934-3-mmenashe@redhat.com
State Changes Requested
Headers show
Series futex: Add error coverage tests for wait, wake and cmp_requeue | expand

Checks

Context Check Description
ltpci/github-build-doc success success
ltpci/github-build-debian_stable_aarch64-linux-gnu-gcc_arm64 success success
ltpci/github-build-debian_stable_powerpc64le-linux-gnu-gcc_ppc64el success success
ltpci/github-build-debian_testing_gcc success success
ltpci/github-build-debian_stable_s390x-linux-gnu-gcc_s390x success success
ltpci/github-build-ubuntu_jammy_gcc success success
ltpci/github-build-debian_stable_gcc success success
ltpci/github-build-fedora_latest_clang success success
ltpci/github-build-alpine_latest_gcc success success
ltpci/github-build-quay-io-centos-centos_stream9_gcc success success
ltpci/github-build-debian_testing_clang success success
ltpci/github-build-debian_stable_gcc success success
ltpci/github-build-debian_oldstable_gcc success success
ltpci/github-build-opensuse-leap_latest_gcc success success
ltpci/github-build-debian_oldstable_clang success success
ltpci/github-build-opensuse-archive_42-2_gcc success success
ltpci/copilot-review success Approved
ltpci/github-build-ubuntu_noble_gcc success success

Commit Message

Michael Menasherov May 7, 2026, 11:18 a.m. UTC
futex(FUTEX_WAIT) has no existing test for EINTR. Add coverage for
the case where the wait is interrupted by a signal before the futex
word changes.

Signed-off-by: Michael Menasherov <mmenashe@redhat.com>
---
 runtest/syscalls                              |  1 +
 testcases/kernel/syscalls/futex/.gitignore    |  1 +
 .../kernel/syscalls/futex/futex_wait07.c      | 88 +++++++++++++++++++
 3 files changed, 90 insertions(+)
 create mode 100644 testcases/kernel/syscalls/futex/futex_wait07.c

Comments

Andrea Cervesato May 19, 2026, 2:47 p.m. UTC | #1
Hi Michael,

> +{
> +	if (futex) {
> +		SAFE_MUNMAP((void *)futex, sizeof(*futex));
> +	}
> +}

Please run `make check` on patches because this is supposed to be
an error: 1 line statement doesn't require parenthesis.

Kind regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
diff mbox series

Patch

diff --git a/runtest/syscalls b/runtest/syscalls
index 621355e04..75b7754db 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1906,3 +1906,4 @@  io_uring03 io_uring03
 # Tests below may cause kernel memory leak
 perf_event_open03 perf_event_open03
 futex_wait06 futex_wait06
+futex_wait07 futex_wait07
diff --git a/testcases/kernel/syscalls/futex/.gitignore b/testcases/kernel/syscalls/futex/.gitignore
index 56596dcb4..74ac9a926 100644
--- a/testcases/kernel/syscalls/futex/.gitignore
+++ b/testcases/kernel/syscalls/futex/.gitignore
@@ -14,3 +14,4 @@ 
 /futex_waitv02
 /futex_waitv03
 /futex_wait06
+/futex_wait07
diff --git a/testcases/kernel/syscalls/futex/futex_wait07.c b/testcases/kernel/syscalls/futex/futex_wait07.c
new file mode 100644
index 000000000..9bf35e506
--- /dev/null
+++ b/testcases/kernel/syscalls/futex/futex_wait07.c
@@ -0,0 +1,88 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Red Hat, Inc.
+ */
+
+/*\
+ * Check that futex(FUTEX_WAIT) returns EINTR when interrupted by a signal.
+ * A child process blocks on futex_wait() with a long timeout. The parent
+ * waits for the child to enter sleep state, then sends SIGUSR1 to it.
+ * The child verifies it received EINTR and exits accordingly.
+ */
+
+#include <errno.h>
+#include <signal.h>
+
+#include "futextest.h"
+
+static futex_t *futex;
+
+static struct futex_test_variants variants[] = {
+#if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
+	{ .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
+	{ .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+/* Empty handler: receiving the signal is sufficient to interrupt futex_wait(). */
+static void sigusr1_handler(int sig LTP_ATTRIBUTE_UNUSED)
+{
+}
+
+static void do_child(void)
+{
+	struct futex_test_variants *tv = &variants[tst_variant];
+	struct sigaction sa;
+	struct tst_ts timeout;
+
+	sa.sa_handler = sigusr1_handler;
+	sa.sa_flags = 0;
+	SAFE_SIGEMPTYSET(&sa.sa_mask);
+	SAFE_SIGACTION(SIGUSR1, &sa, NULL);
+
+	timeout = tst_ts_from_ms(tv->tstype, 5000);
+	TST_EXP_FAIL(futex_wait(tv->fntype, futex, *futex, &timeout, 0), EINTR);
+	exit(0);
+}
+
+static void run(void)
+{
+	pid_t child;
+
+	child = SAFE_FORK();
+
+	if (child == 0)
+		do_child();
+
+	TST_PROCESS_STATE_WAIT(child, 'S', 0);
+	SAFE_KILL(child, SIGUSR1);
+}
+
+static void setup(void)
+{
+	struct futex_test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	futex_supported_by_kernel(tv->fntype);
+
+	futex = SAFE_MMAP(NULL, sizeof(*futex), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+	*futex = FUTEX_INITIALIZER;
+}
+
+static void cleanup(void)
+{
+	if (futex) {
+		SAFE_MUNMAP((void *)futex, sizeof(*futex));
+	}
+}
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
+	.forks_child = 1,
+};