}
static inline int test_run_child(const struct test *t, int fdout[2],
- int fderr[2])
+ int fderr[2], int fdmonitor[2])
{
/* kill child if parent dies */
prctl(PR_SET_PDEATHSIG, SIGTERM);
}
}
+ close(fdmonitor[0]);
+
if (t->config[TC_ROOTFS] != NULL) {
const char *stamp = TESTSUITE_ROOTFS "../stamp-rootfs";
const char *rootfs = t->config[TC_ROOTFS];
}
static inline bool test_run_parent_check_outputs(const struct test *t,
- int fdout, int fderr)
+ int fdout, int fderr, int fdmonitor)
{
- struct epoll_event ep_outpipe, ep_errpipe;
+ struct epoll_event ep_outpipe, ep_errpipe, ep_monitor;
int err, fd_ep, fd_matchout = -1, fd_matcherr = -1;
- if (t->output.stdout == NULL && t->output.stderr == NULL)
- return true;
-
fd_ep = epoll_create1(EPOLL_CLOEXEC);
if (fd_ep < 0) {
ERR("could not create epoll fd: %m\n");
} else
fderr = -1;
- for (err = 0; fdout >= 0 || fderr >= 0;) {
+ memset(&ep_monitor, 0, sizeof(struct epoll_event));
+ ep_monitor.events = EPOLLHUP;
+ ep_monitor.data.ptr = &fdmonitor;
+ if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fdmonitor, &ep_monitor) < 0) {
+ err = -errno;
+ ERR("could not add monitor fd to epoll: %m\n");
+ goto out;
+ }
+
+ for (err = 0; fdmonitor >= 0 || fdout >= 0 || fderr >= 0;) {
int fdcount, i;
struct epoll_event ev[4];
if (*fd == fdout)
fd_match = fd_matchout;
- else
+ else if (*fd == fderr)
fd_match = fd_matcherr;
+ else {
+ ERR("Unexpected activity on monitor pipe\n");
+ err = -EINVAL;
+ goto out;
+ }
for (;;) {
int rmatch = read(fd_match,
}
static inline int test_run_parent(const struct test *t, int fdout[2],
- int fderr[2])
+ int fderr[2], int fdmonitor[2])
{
pid_t pid;
int err;
close(fdout[1]);
if (t->output.stderr != NULL)
close(fderr[1]);
+ close(fdmonitor[1]);
- matchout = test_run_parent_check_outputs(t, fdout[0], fderr[0]);
+ matchout = test_run_parent_check_outputs(t, fdout[0], fderr[0],
+ fdmonitor[0]);
/*
* break pipe on the other end: either child already closed or we want
close(fdout[0]);
if (t->output.stderr != NULL)
close(fderr[0]);
+ close(fdmonitor[0]);
do {
pid = wait(&err);
pid_t pid;
int fdout[2];
int fderr[2];
+ int fdmonitor[2];
if (t->need_spawn && oneshot)
test_run_spawned(t);
}
}
+ if (pipe(fdmonitor) != 0) {
+ ERR("could not create monitor pipe for %s\n", t->name);
+ return EXIT_FAILURE;
+ }
+
if (prepend_path(t->path) < 0) {
ERR("failed to prepend '%s' to PATH\n", t->path);
return EXIT_FAILURE;
}
if (pid > 0)
- return test_run_parent(t, fdout, fderr);
+ return test_run_parent(t, fdout, fderr, fdmonitor);
- return test_run_child(t, fdout, fderr);
+ return test_run_child(t, fdout, fderr, fdmonitor);
}