From 5ba67aeabd081185c7746132c4960f6c607f3539 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Mon, 6 Mar 2023 03:04:13 +0900 Subject: [PATCH] tests: (mkfds) add eventfd factory Signed-off-by: Masatake YAMATO --- tests/helpers/test_mkfds.c | 137 +++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/tests/helpers/test_mkfds.c b/tests/helpers/test_mkfds.c index 2aad1dacf6..540fc50240 100644 --- a/tests/helpers/test_mkfds.c +++ b/tests/helpers/test_mkfds.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include #include "c.h" @@ -60,6 +62,7 @@ #define _U_ __attribute__((__unused__)) static int pidfd_open(pid_t pid, unsigned int flags); +static void do_nothing(int signum _U_); static void __attribute__((__noreturn__)) usage(FILE *out, int status) { @@ -324,6 +327,13 @@ static void close_fdesc(int fd, void *data _U_) close(fd); } +static void abort_with_child_death_message(int signum _U_) +{ + const char msg[] = "the child process exits unexpectedly"; + (void)write(2, msg, sizeof(msg)); + _exit(EXIT_FAILURE); +} + static void *open_ro_regular_file(const struct factory *factory, struct fdesc fdescs[], int argc, char ** argv) { @@ -1888,6 +1898,119 @@ static void *make_netlink(const struct factory *factory, struct fdesc fdescs[], return NULL; } +static void *make_eventfd(const struct factory *factory _U_, struct fdesc fdescs[], + int argc _U_, char ** argv _U_) +{ + int fd; + pid_t *pid = xcalloc(1, sizeof(*pid)); + + if (fdescs[0].fd == fdescs[1].fd) + errx(EXIT_FAILURE, "specify three different numbers as file descriptors"); + + fd = eventfd(0, 0); + if (fd < 0) + err(EXIT_FAILURE, "failed in eventfd(2)"); + + if (fd != fdescs[0].fd) { + if (dup2(fd, fdescs[0].fd) < 0) { + int e = errno; + close(fd); + errno = e; + err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd); + } + close(fd); + } + + fdescs[0] = (struct fdesc){ + .fd = fdescs[0].fd, + .close = close_fdesc, + .data = NULL + }; + + if (dup2(fdescs[0].fd, fdescs[1].fd) < 0) { + int e = errno; + close(fdescs[0].fd); + errno = e; + err(EXIT_FAILURE, "failed to dup %d -> %d", fdescs[0].fd, fdescs[1].fd); + } + + signal(SIGCHLD, abort_with_child_death_message); + *pid = fork(); + if (*pid < -1) { + int e = errno; + close(fdescs[0].fd); + close(fdescs[1].fd); + errno = e; + err(EXIT_FAILURE, "failed in fork()"); + } else if (*pid == 0) { + uint64_t v = 1; + + free(pid); + close(fdescs[0].fd); + + signal(SIGCONT, do_nothing); + /* Notify the parent that I'm ready. */ + if (write(fdescs[1].fd, &v, sizeof(v)) != sizeof(v)) { + close(fdescs[1].fd); + err(EXIT_FAILURE, + "failed in write() to notify the readiness to the prent"); + } + /* Wait till the parent lets me go. */ + pause(); + + close(fdescs[1].fd); + exit(0); + } else { + uint64_t v; + + /* The child owns fdescs[1]. */ + close(fdescs[1].fd); + fdescs[1].fd = -1; + + /* Wait till the child is ready. */ + if (read(fdescs[0].fd, &v, sizeof(uint64_t)) != sizeof(v)) { + free(pid); + close(fdescs[0].fd); + err(EXIT_FAILURE, + "failed in read() the readiness notification from the child"); + } + signal(SIGCHLD, SIG_DFL); + } + + return pid; +} + +static void report_eventfd(const struct factory *factory _U_, + int nth, void *data, FILE *fp) +{ + if (nth == 0) { + pid_t *child = data; + fprintf(fp, "%d", *child); + } +} + +static void free_eventfd(const struct factory * factory _U_, void *data) +{ + pid_t child = *(pid_t *)data; + int wstatus; + + free(data); + + kill(child, SIGCONT); + if (waitpid(child, &wstatus, 0) < 0) + err(EXIT_FAILURE, "failed in waitpid()"); + + if (WIFEXITED(wstatus)) { + int s = WEXITSTATUS(wstatus); + if (s != 0) + err(EXIT_FAILURE, "the child process got an error: %d", s); + } else if (WIFSIGNALED(wstatus)) { + int s = WTERMSIG(wstatus); + if (WTERMSIG(wstatus) != 0) + err(EXIT_FAILURE, "the child process got a signal: %d", s); + } +} + #define PARAM_END { .name = NULL, } static const struct factory factories[] = { { @@ -2451,6 +2574,20 @@ static const struct factory factories[] = { PARAM_END } }, + { + .name = "eventfd", + .desc = "make an eventfd connecting two processes", + .priv = false, + .N = 2, + .EX_N = 0, + .EX_R = 1, + .make = make_eventfd, + .report = report_eventfd, + .free = free_eventfd, + .params = (struct parameter []) { + PARAM_END + } + }, }; static int count_parameters(const struct factory *factory) -- 2.47.3