diff --git a/ChangeLog b/ChangeLog index 3eba2d5e729c00ab9f4bf48d988f6aaa98b676a1..a4e52d7af68bbb81c1414e0d766ca12abe742151 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Aug 20 09:59:54 BST 2008 Daniel P. Berrange + + * src/util.c: Allow a pre-opened FD to be passed in for childs + stdout/err + * src/openvz_driver.c, src/qemu_driver.c: Initialize FDs to + -1 before calling virExec() + Wed Aug 20 09:35:33 BST 2008 Daniel P. Berrange Avoid signal race in virExec() diff --git a/src/openvz_driver.c b/src/openvz_driver.c index 0d0eac1af7e53aabfeec8f3da22186e1f838e0fd..886a42af595ea32d813d93308252d18b96186b61 100644 --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -736,7 +736,9 @@ static int openvzGetNodeInfo(virConnectPtr conn, static int openvzListDomains(virConnectPtr conn, int *ids, int nids) { int got = 0; - int veid, pid, outfd, errfd; + int veid, pid; + int outfd = -1; + int errfd = -1; int ret; char buf[32]; char *endptr; @@ -772,7 +774,7 @@ static int openvzNumDomains(virConnectPtr conn ATTRIBUTE_UNUSED) { 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 --git a/src/qemu_driver.c b/src/qemu_driver.c index 2398686ced80c6fcbadc89c5fa7e550ad4b725e4..6d5171f254798799a356c6a3d60ccfc962355358 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -949,6 +949,9 @@ static int qemudStartVMDaemon(virConnectPtr conn, qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s\n"), errno, strerror(errno)); + vm->stdout_fd = -1; + vm->stderr_fd = -1; + ret = virExecNonBlock(conn, argv, &vm->pid, vm->stdin_fd, &vm->stdout_fd, &vm->stderr_fd); if (ret == 0) { diff --git a/src/util.c b/src/util.c index 731145303520460cc852dddbbc66cddee59cd411..483da5d7406bdc5ec0937db6ce2e2188ebb6e1b8 100644 --- a/src/util.c +++ b/src/util.c @@ -118,6 +118,8 @@ _virExec(virConnectPtr conn, int pid, null, i; int pipeout[2] = {-1,-1}; int pipeerr[2] = {-1,-1}; + int childout = -1; + int childerr = -1; sigset_t oldmask, newmask; struct sigaction sig_action; @@ -140,39 +142,66 @@ _virExec(virConnectPtr conn, 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 (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 (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; + 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 (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; + + if (errfd != NULL) { + if (*errfd == -1) { + if (pipe(pipeerr) < 0) { + ReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to 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; } +#ifndef ENABLE_DEBUG + } else { + childerr = null; +#endif } if ((pid = fork()) < 0) { @@ -183,11 +212,11 @@ _virExec(virConnectPtr conn, 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]; } @@ -250,35 +279,25 @@ _virExec(virConnectPtr conn, _("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);