VIR_EXEC_CLEAR_CAPS = (1 << 2),
VIR_EXEC_RUN_SYNC = (1 << 3),
VIR_EXEC_ASYNC_IO = (1 << 4),
- VIR_EXEC_LISTEN_FDS = (1 << 5),
};
typedef struct _virCommandFD virCommandFD;
#ifndef WIN32
-static void
-virCommandReorderFDs(virCommandPtr cmd)
-{
- int maxfd = 0;
- int openmax = 0;
- size_t i = 0;
-
- if (!cmd || cmd->has_error || !cmd->npassfd)
- return;
-
- for (i = 0; i < cmd->npassfd; i++)
- maxfd = MAX(cmd->passfd[i].fd, maxfd);
-
- openmax = sysconf(_SC_OPEN_MAX);
- if (openmax < 0 ||
- maxfd + cmd->npassfd > openmax)
- goto error;
-
- /*
- * Simple two-pass sort, nothing fancy. This is not designed for
- * anything else than passing around 2 FDs into the child.
- *
- * So first dup2() them somewhere else.
- */
- for (i = 0; i < cmd->npassfd; i++) {
- int newfd = maxfd + i + 1;
- int oldfd = cmd->passfd[i].fd;
- if (dup2(oldfd, newfd) != newfd) {
- virReportSystemError(errno,
- _("Cannot dup2() fd %d before "
- "passing it to the child"),
- oldfd);
- goto error;
- }
- VIR_FORCE_CLOSE(cmd->passfd[i].fd);
- }
-
- VIR_DEBUG("First reorder pass done");
-
- /*
- * And then dup2() them in orderly manner.
- */
- for (i = 0; i < cmd->npassfd; i++) {
- int newfd = STDERR_FILENO + i + 1;
- int oldfd = maxfd + i + 1;
- if (dup2(oldfd, newfd) != newfd) {
- virReportSystemError(errno,
- _("Cannot dup2() fd %d before "
- "passing it to the child"),
- oldfd);
- goto error;
- }
- if (virSetInherit(newfd, true) < 0) {
- virReportSystemError(errno,
- _("Cannot set O_CLOEXEC on fd %d before "
- "passing it to the child"),
- newfd);
- goto error;
- }
- VIR_FORCE_CLOSE(oldfd);
- cmd->passfd[i].fd = newfd;
- }
-
- VIR_DEBUG("Second reorder pass done");
-
- return;
-
- error:
- cmd->has_error = -1;
- return;
-}
-
/**
* virFork:
*
goto fork_error;
}
- if (cmd->flags & VIR_EXEC_LISTEN_FDS) {
- virCommandReorderFDs(cmd);
- virCommandAddEnvFormat(cmd, "LISTEN_PID=%u", getpid());
- virCommandAddEnvFormat(cmd, "LISTEN_FDS=%zu", cmd->npassfd);
-
- if (cmd->has_error)
- goto fork_error;
- }
-
/* Close logging again to ensure no FDs leak to child */
virLogReset();
}
}
-/**
- * virCommandPassListenFDs:
- * @cmd: the command to modify
- *
- * Pass LISTEN_FDS and LISTEN_PID environment variables into the
- * child. LISTEN_PID has the value of the child's PID and LISTEN_FDS
- * is a number of passed file descriptors starting from 3.
- */
-void
-virCommandPassListenFDs(virCommandPtr cmd)
-{
- if (!cmd || cmd->has_error)
- return;
-
- cmd->flags |= VIR_EXEC_LISTEN_FDS;
-}
-
/*
* virCommandPassFDGetFDIndex:
* @cmd: pointer to virCommand
return ret;
}
-static int test24(const void *unused ATTRIBUTE_UNUSED)
-{
- char *pidfile = virPidFileBuildPath(abs_builddir, "commandhelper");
- char *prefix = NULL;
- int newfd1 = dup(STDERR_FILENO);
- int newfd2 = dup(STDERR_FILENO);
- int newfd3 = dup(STDERR_FILENO);
- int ret = -1;
- pid_t pid;
- virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
-
- if (!pidfile)
- goto cleanup;
-
- if (VIR_CLOSE(newfd1) < 0)
- printf("Cannot close fd %d\n", newfd1);
-
- virCommandSetPidFile(cmd, pidfile);
- virCommandDaemonize(cmd);
- virCommandPassFD(cmd, newfd2, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
- virCommandPassFD(cmd, newfd3, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
- newfd2 = newfd3 = -1;
- virCommandPassListenFDs(cmd);
-
- if (virCommandRun(cmd, NULL) < 0) {
- printf("Cannot run child %s\n", virGetLastErrorMessage());
- goto cleanup;
- }
-
- if (virPidFileRead(abs_builddir, "commandhelper", &pid) < 0) {
- printf("cannot read pidfile\n");
- goto cleanup;
- }
-
- if (virAsprintf(&prefix,
- "ENV:LISTEN_FDS=2\nENV:LISTEN_PID=%u\n",
- pid) < 0)
- goto cleanup;
-
- while (kill(pid, 0) != -1)
- usleep(100*1000);
-
- ret = checkoutput("test24", prefix);
-
- cleanup:
- if (pidfile)
- unlink(pidfile);
- VIR_FREE(pidfile);
- VIR_FREE(prefix);
- virCommandFree(cmd);
- VIR_FORCE_CLOSE(newfd1);
- VIR_FORCE_CLOSE(newfd2);
- VIR_FORCE_CLOSE(newfd3);
- return ret;
-}
-
-
static int test25(const void *unused ATTRIBUTE_UNUSED)
{
int ret = -1;
DO_TEST(test21);
DO_TEST(test22);
DO_TEST(test23);
- DO_TEST(test24);
DO_TEST(test25);
DO_TEST(test26);