
All of the new pidfd selftests already use the new kselftest harness infrastructure. It makes for clearer output, makes the code easier to understand, and makes adding new tests way simpler. Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Shuah Khan <shuah@kernel.org> Cc: linux-kselftest@vger.kernel.org Link: https://lore.kernel.org/r/20200902102130.147672-4-christian.brauner@ubuntu.com
137 lines
3.1 KiB
C
137 lines
3.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#define _GNU_SOURCE
|
|
#include <errno.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/types.h>
|
|
#include <signal.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sched.h>
|
|
#include <string.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include "pidfd.h"
|
|
#include "../kselftest_harness.h"
|
|
|
|
#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
|
|
|
|
static pid_t sys_clone3(struct clone_args *args)
|
|
{
|
|
return syscall(__NR_clone3, args, sizeof(struct clone_args));
|
|
}
|
|
|
|
static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
|
|
struct rusage *ru)
|
|
{
|
|
return syscall(__NR_waitid, which, pid, info, options, ru);
|
|
}
|
|
|
|
TEST(wait_simple)
|
|
{
|
|
int pidfd = -1, status = 0;
|
|
pid_t parent_tid = -1;
|
|
struct clone_args args = {
|
|
.parent_tid = ptr_to_u64(&parent_tid),
|
|
.pidfd = ptr_to_u64(&pidfd),
|
|
.flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
|
|
.exit_signal = SIGCHLD,
|
|
};
|
|
int ret;
|
|
pid_t pid;
|
|
siginfo_t info = {
|
|
.si_signo = 0,
|
|
};
|
|
|
|
pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
|
|
ASSERT_GE(pidfd, 0);
|
|
|
|
pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
|
|
ASSERT_NE(pid, 0);
|
|
EXPECT_EQ(close(pidfd), 0);
|
|
pidfd = -1;
|
|
|
|
pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
|
ASSERT_GE(pidfd, 0);
|
|
|
|
pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
|
|
ASSERT_NE(pid, 0);
|
|
EXPECT_EQ(close(pidfd), 0);
|
|
pidfd = -1;
|
|
|
|
pid = sys_clone3(&args);
|
|
ASSERT_GE(pid, 1);
|
|
|
|
if (pid == 0)
|
|
exit(EXIT_SUCCESS);
|
|
|
|
pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
|
|
ASSERT_GE(pid, 0);
|
|
ASSERT_EQ(WIFEXITED(info.si_status), true);
|
|
ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
|
|
EXPECT_EQ(close(pidfd), 0);
|
|
|
|
ASSERT_EQ(info.si_signo, SIGCHLD);
|
|
ASSERT_EQ(info.si_code, CLD_EXITED);
|
|
ASSERT_EQ(info.si_pid, parent_tid);
|
|
}
|
|
|
|
TEST(wait_states)
|
|
{
|
|
int pidfd = -1, status = 0;
|
|
pid_t parent_tid = -1;
|
|
struct clone_args args = {
|
|
.parent_tid = ptr_to_u64(&parent_tid),
|
|
.pidfd = ptr_to_u64(&pidfd),
|
|
.flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
|
|
.exit_signal = SIGCHLD,
|
|
};
|
|
int ret;
|
|
pid_t pid;
|
|
siginfo_t info = {
|
|
.si_signo = 0,
|
|
};
|
|
|
|
pid = sys_clone3(&args);
|
|
ASSERT_GE(pid, 0);
|
|
|
|
if (pid == 0) {
|
|
kill(getpid(), SIGSTOP);
|
|
kill(getpid(), SIGSTOP);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
|
|
ASSERT_EQ(info.si_signo, SIGCHLD);
|
|
ASSERT_EQ(info.si_code, CLD_STOPPED);
|
|
ASSERT_EQ(info.si_pid, parent_tid);
|
|
|
|
ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
|
|
|
|
ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
|
|
ASSERT_EQ(info.si_signo, SIGCHLD);
|
|
ASSERT_EQ(info.si_code, CLD_CONTINUED);
|
|
ASSERT_EQ(info.si_pid, parent_tid);
|
|
|
|
ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL), 0);
|
|
ASSERT_EQ(info.si_signo, SIGCHLD);
|
|
ASSERT_EQ(info.si_code, CLD_STOPPED);
|
|
ASSERT_EQ(info.si_pid, parent_tid);
|
|
|
|
ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
|
|
|
|
ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
|
|
ASSERT_EQ(info.si_signo, SIGCHLD);
|
|
ASSERT_EQ(info.si_code, CLD_KILLED);
|
|
ASSERT_EQ(info.si_pid, parent_tid);
|
|
|
|
EXPECT_EQ(close(pidfd), 0);
|
|
}
|
|
|
|
TEST_HARNESS_MAIN
|