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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list