mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge patch series "selftests/namespaces: Fix test hangs and false failures"
Ricardo B. Marlière <rbm@suse.com> says: This series addresses three reliability problems in the namespaces selftest suite that cause tests to hang or report incorrect results. The first patch fixes a hang in nsid_test where the grandchild process is not reaped during fixture teardown, leaving it alive and holding the TAP pipe write-end open so the test runner blocks indefinitely waiting for EOF. The second and third patches fix two problems in listns_efault_test: a waitpid(-1) race that can cause the iterator child to be consumed during namespace cleanup (leading to an indefinite block on the subsequent targeted waitpid), and a false FAIL verdict on kernels that do not implement listns() (the EFAULT tests should SKIP in that case, consistent with every other listns test that already handles ENOSYS correctly). Link: https://patch.msgid.link/20260407-selftests-namespaces_fixes-v1-0-59109909d88b@suse.com Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
commit
a243a7b02e
|
|
@ -38,7 +38,7 @@ TEST(listns_partial_fault_with_ns_cleanup)
|
|||
__u64 *ns_ids;
|
||||
ssize_t ret;
|
||||
long page_size;
|
||||
pid_t pid, iter_pid;
|
||||
pid_t pid, iter_pid, ns_pids[5];
|
||||
int pidfds[5];
|
||||
int sv[5][2];
|
||||
int iter_pidfd;
|
||||
|
|
@ -114,6 +114,7 @@ TEST(listns_partial_fault_with_ns_cleanup)
|
|||
|
||||
pid = create_child(&pidfds[i], CLONE_NEWNS);
|
||||
ASSERT_NE(pid, -1);
|
||||
ns_pids[i] = pid;
|
||||
|
||||
if (pid == 0) {
|
||||
close(sv[i][0]); /* Close parent end */
|
||||
|
|
@ -164,7 +165,7 @@ TEST(listns_partial_fault_with_ns_cleanup)
|
|||
|
||||
/* Wait for all mount namespace children to exit and cleanup */
|
||||
for (i = 0; i < 5; i++) {
|
||||
waitpid(-1, NULL, 0);
|
||||
waitpid(ns_pids[i], NULL, 0);
|
||||
close(sv[i][0]);
|
||||
close(pidfds[i]);
|
||||
}
|
||||
|
|
@ -175,6 +176,12 @@ TEST(listns_partial_fault_with_ns_cleanup)
|
|||
ASSERT_EQ(ret, iter_pid);
|
||||
close(iter_pidfd);
|
||||
|
||||
/* If listns() is not supported the iterator exits cleanly via ENOSYS */
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
|
||||
munmap(map, page_size);
|
||||
SKIP(return, "listns() not supported");
|
||||
}
|
||||
|
||||
/* Should have been killed */
|
||||
ASSERT_TRUE(WIFSIGNALED(status));
|
||||
ASSERT_EQ(WTERMSIG(status), SIGKILL);
|
||||
|
|
@ -250,7 +257,7 @@ TEST(listns_late_fault_with_ns_cleanup)
|
|||
__u64 *ns_ids;
|
||||
ssize_t ret;
|
||||
long page_size;
|
||||
pid_t pid, iter_pid;
|
||||
pid_t pid, iter_pid, ns_pids[10];
|
||||
int pidfds[10];
|
||||
int sv[10][2];
|
||||
int iter_pidfd;
|
||||
|
|
@ -320,6 +327,7 @@ TEST(listns_late_fault_with_ns_cleanup)
|
|||
|
||||
pid = create_child(&pidfds[i], CLONE_NEWNS);
|
||||
ASSERT_NE(pid, -1);
|
||||
ns_pids[i] = pid;
|
||||
|
||||
if (pid == 0) {
|
||||
close(sv[i][0]); /* Close parent end */
|
||||
|
|
@ -373,7 +381,7 @@ TEST(listns_late_fault_with_ns_cleanup)
|
|||
|
||||
/* Wait for all children and cleanup */
|
||||
for (i = 0; i < 10; i++) {
|
||||
waitpid(-1, NULL, 0);
|
||||
waitpid(ns_pids[i], NULL, 0);
|
||||
close(sv[i][0]);
|
||||
close(pidfds[i]);
|
||||
}
|
||||
|
|
@ -384,6 +392,12 @@ TEST(listns_late_fault_with_ns_cleanup)
|
|||
ASSERT_EQ(ret, iter_pid);
|
||||
close(iter_pidfd);
|
||||
|
||||
/* If listns() is not supported the iterator exits cleanly via ENOSYS */
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
|
||||
munmap(map, page_size);
|
||||
SKIP(return, "listns() not supported");
|
||||
}
|
||||
|
||||
/* Should have been killed */
|
||||
ASSERT_TRUE(WIFSIGNALED(status));
|
||||
ASSERT_EQ(WTERMSIG(status), SIGKILL);
|
||||
|
|
@ -402,7 +416,7 @@ TEST(listns_mnt_ns_cleanup_on_fault)
|
|||
__u64 *ns_ids;
|
||||
ssize_t ret;
|
||||
long page_size;
|
||||
pid_t pid, iter_pid;
|
||||
pid_t pid, iter_pid, ns_pids[8];
|
||||
int pidfds[8];
|
||||
int sv[8][2];
|
||||
int iter_pidfd;
|
||||
|
|
@ -462,6 +476,7 @@ TEST(listns_mnt_ns_cleanup_on_fault)
|
|||
|
||||
pid = create_child(&pidfds[i], CLONE_NEWNS);
|
||||
ASSERT_NE(pid, -1);
|
||||
ns_pids[i] = pid;
|
||||
|
||||
if (pid == 0) {
|
||||
close(sv[i][0]); /* Close parent end */
|
||||
|
|
@ -508,7 +523,7 @@ TEST(listns_mnt_ns_cleanup_on_fault)
|
|||
|
||||
/* Wait for children and cleanup */
|
||||
for (i = 0; i < 8; i++) {
|
||||
waitpid(-1, NULL, 0);
|
||||
waitpid(ns_pids[i], NULL, 0);
|
||||
close(sv[i][0]);
|
||||
close(pidfds[i]);
|
||||
}
|
||||
|
|
@ -519,6 +534,12 @@ TEST(listns_mnt_ns_cleanup_on_fault)
|
|||
ASSERT_EQ(ret, iter_pid);
|
||||
close(iter_pidfd);
|
||||
|
||||
/* If listns() is not supported the iterator exits cleanly via ENOSYS */
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
|
||||
munmap(map, page_size);
|
||||
SKIP(return, "listns() not supported");
|
||||
}
|
||||
|
||||
/* Should have been killed */
|
||||
ASSERT_TRUE(WIFSIGNALED(status));
|
||||
ASSERT_EQ(WTERMSIG(status), SIGKILL);
|
||||
|
|
|
|||
|
|
@ -25,14 +25,24 @@
|
|||
/* Fixture for tests that create child processes */
|
||||
FIXTURE(nsid) {
|
||||
pid_t child_pid;
|
||||
pid_t grandchild_pid;
|
||||
};
|
||||
|
||||
FIXTURE_SETUP(nsid) {
|
||||
self->child_pid = 0;
|
||||
self->grandchild_pid = 0;
|
||||
}
|
||||
|
||||
FIXTURE_TEARDOWN(nsid) {
|
||||
/* Clean up any child process that may still be running */
|
||||
/*
|
||||
* Kill grandchild first: timens_separate and pidns_separate fork a
|
||||
* grandchild that calls pause(). It is reparented to init on child
|
||||
* exit and keeps the test runner's tap pipe open, hanging the runner.
|
||||
*/
|
||||
if (self->grandchild_pid > 0) {
|
||||
kill(self->grandchild_pid, SIGKILL);
|
||||
waitpid(self->grandchild_pid, NULL, 0);
|
||||
}
|
||||
if (self->child_pid > 0) {
|
||||
kill(self->child_pid, SIGKILL);
|
||||
waitpid(self->child_pid, NULL, 0);
|
||||
|
|
@ -676,6 +686,7 @@ TEST_F(nsid, timens_separate)
|
|||
|
||||
pid_t grandchild_pid;
|
||||
ASSERT_EQ(read(pipefd[0], &grandchild_pid, sizeof(grandchild_pid)), sizeof(grandchild_pid));
|
||||
self->grandchild_pid = grandchild_pid;
|
||||
close(pipefd[0]);
|
||||
|
||||
/* Open grandchild's time namespace */
|
||||
|
|
@ -797,6 +808,7 @@ TEST_F(nsid, pidns_separate)
|
|||
|
||||
pid_t grandchild_pid;
|
||||
ASSERT_EQ(read(pipefd[0], &grandchild_pid, sizeof(grandchild_pid)), sizeof(grandchild_pid));
|
||||
self->grandchild_pid = grandchild_pid;
|
||||
close(pipefd[0]);
|
||||
|
||||
/* Open grandchild's PID namespace */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user