summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/pidfd/pidfd_info_test.c
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2025-03-20 16:24:09 +0300
committerChristian Brauner <brauner@kernel.org>2025-03-20 17:32:43 +0300
commitdb7ce91e226df0fec200bd2a0eb87eed7c5d3adb (patch)
treeb8d183702d2fed5dfe1ec1cff9a28a3c42f47f20 /tools/testing/selftests/pidfd/pidfd_info_test.c
parent0fb482728ba1ee2130eaa461bf551f014447997c (diff)
downloadlinux-db7ce91e226df0fec200bd2a0eb87eed7c5d3adb.tar.xz
selftests/pidfd: first test for multi-threaded exec polling
Add first test for premature thread-group leader exit. Link: https://lore.kernel.org/r/20250320-work-pidfs-thread_group-v4-2-da678ce805bf@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'tools/testing/selftests/pidfd/pidfd_info_test.c')
-rw-r--r--tools/testing/selftests/pidfd/pidfd_info_test.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/tools/testing/selftests/pidfd/pidfd_info_test.c b/tools/testing/selftests/pidfd/pidfd_info_test.c
index 09bc4ae7aed5..28a28ae4686a 100644
--- a/tools/testing/selftests/pidfd/pidfd_info_test.c
+++ b/tools/testing/selftests/pidfd/pidfd_info_test.c
@@ -236,7 +236,7 @@ static void *pidfd_info_pause_thread(void *arg)
TEST_F(pidfd_info, thread_group)
{
- pid_t pid_leader, pid_thread;
+ pid_t pid_leader, pid_poller, pid_thread;
pthread_t thread;
int nevents, pidfd_leader, pidfd_thread, pidfd_leader_thread, ret;
int ipc_sockets[2];
@@ -262,6 +262,35 @@ TEST_F(pidfd_info, thread_group)
syscall(__NR_exit, EXIT_SUCCESS);
}
+ /*
+ * Opening a PIDFD_THREAD aka thread-specific pidfd based on a
+ * thread-group leader must succeed.
+ */
+ pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
+ ASSERT_GE(pidfd_leader_thread, 0);
+
+ pid_poller = fork();
+ ASSERT_GE(pid_poller, 0);
+ if (pid_poller == 0) {
+ /*
+ * We can't poll and wait for the old thread-group
+ * leader to exit using a thread-specific pidfd. The
+ * thread-group leader exited prematurely and
+ * notification is delayed until all subthreads have
+ * exited.
+ */
+ fds.events = POLLIN;
+ fds.fd = pidfd_leader_thread;
+ nevents = poll(&fds, 1, 10000 /* wait 5 seconds */);
+ if (nevents != 0)
+ _exit(EXIT_FAILURE);
+ if (fds.revents & POLLIN)
+ _exit(EXIT_FAILURE);
+ if (fds.revents & POLLHUP)
+ _exit(EXIT_FAILURE);
+ _exit(EXIT_SUCCESS);
+ }
+
/* Retrieve the tid of the thread. */
EXPECT_EQ(close(ipc_sockets[1]), 0);
ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
@@ -275,12 +304,7 @@ TEST_F(pidfd_info, thread_group)
pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
ASSERT_GE(pidfd_thread, 0);
- /*
- * Opening a PIDFD_THREAD aka thread-specific pidfd based on a
- * thread-group leader must succeed.
- */
- pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
- ASSERT_GE(pidfd_leader_thread, 0);
+ ASSERT_EQ(wait_for_pid(pid_poller), 0);
/*
* Note that pidfd_leader is a thread-group pidfd, so polling on it