The contract for virExec() currently allows the caller to pass in a NULL
for stdout/err parameters in which case the child will be connected to
/dev/null, or they can pass in a pointer to an int, in which case the
child will be connected to a pair of pipes, and the read end of the pipe
is returned to the caller.
The LXC driver will require a 3rd option - we want to pass in a existing
file handler connected to a logfile. So this patch extends the semantics
of these two parameters. If the stderr/out params are non-NULL, but are
initialized to -1, then a pipe will be allocated. If they are >= 0, then
they are assumed to be existing FDs to dup onto the child's stdout/err.
This change neccessitated updating all existing callers of virExec to
make sure they initialize the parameters to -1 to maintain existing
behaviour.
openvz_driver.c | 4 -
qemu_driver.c | 2
util.c | 120 ++++++++++++++++++++++++++++++++------------------------
3 files changed, 73 insertions(+), 53 deletions(-)
Daniel
diff -r 100b059a8488 src/openvz_driver.c
--- a/src/openvz_driver.c Tue Aug 12 22:12:38 2008 +0100
+++ b/src/openvz_driver.c Tue Aug 12 22:12:42 2008 +0100
@@ -736,7 +736,7 @@
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
int got = 0;
- int veid, pid, outfd, errfd;
+ int veid, pid, outfd = -1, errfd = -1;
int ret;
char buf[32];
char *endptr;
@@ -772,7 +772,7 @@
static int openvzListDefinedDomains(virConnectPtr conn,
char **const names, int nnames) {
int got = 0;
- int veid, pid, outfd, errfd, ret;
+ int veid, pid, outfd = -1, errfd = -1, ret;
char vpsname[OPENVZ_NAME_MAX];
char buf[32];
char *endptr;
diff -r 100b059a8488 src/qemu_driver.c
--- a/src/qemu_driver.c Tue Aug 12 22:12:38 2008 +0100
+++ b/src/qemu_driver.c Tue Aug 12 22:12:42 2008 +0100
@@ -948,6 +948,8 @@
if (safewrite(vm->logfile, "\n", 1) < 0)
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s\n"),
errno, strerror(errno));
+
+ vm->stdout_fd = vm->stderr_fd = -1;
ret = virExecNonBlock(conn, argv, &vm->pid,
vm->stdin_fd, &vm->stdout_fd,
&vm->stderr_fd);
diff -r 100b059a8488 src/util.c
--- a/src/util.c Tue Aug 12 22:12:38 2008 +0100
+++ b/src/util.c Tue Aug 12 22:12:42 2008 +0100
@@ -110,6 +110,7 @@
int pid, null, i;
int pipeout[2] = {-1,-1};
int pipeerr[2] = {-1,-1};
+ int childout = -1, childerr = -1;
sigset_t oldmask, newmask;
struct sigaction sig_action;
@@ -132,39 +133,66 @@
goto cleanup;
}
- if ((outfd != NULL && pipe(pipeout) < 0) ||
- (errfd != NULL && pipe(pipeerr) < 0)) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("cannot create pipe: %s"), strerror(errno));
- goto cleanup;
+ if (outfd != NULL) {
+ if (*outfd == -1) {
+ if (pipe(pipeout) < 0) {
+ ReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot create pipe: %s"), strerror(errno));
+ goto cleanup;
+ }
+
+ if (non_block &&
+ virSetNonBlock(pipeout[0]) == -1) {
+ ReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set non-blocking file descriptor
flag"));
+ goto cleanup;
+ }
+
+ if (virSetCloseExec(pipeout[0]) == -1) {
+ ReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set close-on-exec file descriptor
flag"));
+ goto cleanup;
+ }
+
+ childout = pipeout[1];
+ } else {
+ childout = *outfd;
+ }
+#ifndef ENABLE_DEBUG
+ } else {
+ childout = null;
+#endif
}
- if (outfd) {
- if(non_block &&
- virSetNonBlock(pipeout[0]) == -1) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Failed to set non-blocking file descriptor flag"));
- goto cleanup;
+ if (errfd != NULL) {
+ if (*errfd == -1) {
+ if (pipe(pipeerr) < 0) {
+ ReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot create pipe: %s"), strerror(errno));
+ goto cleanup;
+ }
+
+ if (non_block &&
+ virSetNonBlock(pipeerr[0]) == -1) {
+ ReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set non-blocking file descriptor
flag"));
+ goto cleanup;
+ }
+
+ if (virSetCloseExec(pipeerr[0]) == -1) {
+ ReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to set close-on-exec file descriptor
flag"));
+ goto cleanup;
+ }
+
+ childerr = pipeerr[1];
+ } else {
+ childerr = *errfd;
}
-
- if(virSetCloseExec(pipeout[0]) == -1) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Failed to set close-on-exec file descriptor
flag"));
- goto cleanup;
- }
- }
- if (errfd) {
- if(non_block &&
- virSetNonBlock(pipeerr[0]) == -1) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Failed to set non-blocking file descriptor flag"));
- goto cleanup;
- }
- if(virSetCloseExec(pipeerr[0]) == -1) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Failed to set close-on-exec file descriptor
flag"));
- goto cleanup;
- }
+#ifndef ENABLE_DEBUG
+ } else {
+ childerr = null;
+#endif
}
if ((pid = fork()) < 0) {
@@ -175,11 +203,11 @@
if (pid) { /* parent */
close(null);
- if (outfd) {
+ if (outfd && *outfd == -1) {
close(pipeout[1]);
*outfd = pipeout[0];
}
- if (errfd) {
+ if (errfd && *errfd == -1) {
close(pipeerr[1]);
*errfd = pipeerr[0];
}
@@ -242,35 +270,25 @@
_("failed to setup stdin file handle: %s"),
strerror(errno));
_exit(1);
}
-#ifndef ENABLE_DEBUG
- if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0) {
+ if (childout > 0 &&
+ dup2(childout, STDOUT_FILENO) < 0) {
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("failed to setup stdout file handle: %s"),
strerror(errno));
_exit(1);
}
- if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0) {
+ if (childerr > 0 &&
+ dup2(childerr, STDERR_FILENO) < 0) {
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("failed to setup stderr file handle: %s"),
strerror(errno));
_exit(1);
}
-#else /* ENABLE_DEBUG */
- if (pipeout[1] > 0 && dup2(pipeout[1], STDOUT_FILENO) < 0) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("failed to setup stderr file handle: %s"),
strerror(errno));
- _exit(1);
- }
- if (pipeerr[1] > 0 && dup2(pipeerr[1], STDERR_FILENO) < 0) {
- ReportError(conn, VIR_ERR_INTERNAL_ERROR,
- _("failed to setup stdout file handle: %s"),
strerror(errno));
- _exit(1);
- }
-#endif /* ENABLE_DEBUG */
close(null);
- if (pipeout[1] > 0)
- close(pipeout[1]);
- if (pipeerr[1] > 0)
- close(pipeerr[1]);
+ if (childout > 0)
+ close(childout);
+ if (childerr > 0 &&
+ childerr != childout)
+ close(childerr);
execvp(argv[0], (char **) argv);
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|