mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Allow a pre-opened FD to be be pass to virExec for stdout/err
This commit is contained in:
parent
60ed1d2a7a
commit
6bc99a7775
@ -1,3 +1,10 @@
|
|||||||
|
Wed Aug 20 09:59:54 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* 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 <berrange@redhat.com>
|
Wed Aug 20 09:35:33 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
Avoid signal race in virExec()
|
Avoid signal race in virExec()
|
||||||
|
@ -736,7 +736,9 @@ static int openvzGetNodeInfo(virConnectPtr conn,
|
|||||||
|
|
||||||
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
|
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
|
||||||
int got = 0;
|
int got = 0;
|
||||||
int veid, pid, outfd, errfd;
|
int veid, pid;
|
||||||
|
int outfd = -1;
|
||||||
|
int errfd = -1;
|
||||||
int ret;
|
int ret;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
char *endptr;
|
char *endptr;
|
||||||
@ -772,7 +774,7 @@ static int openvzNumDomains(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
|||||||
static int openvzListDefinedDomains(virConnectPtr conn,
|
static int openvzListDefinedDomains(virConnectPtr conn,
|
||||||
char **const names, int nnames) {
|
char **const names, int nnames) {
|
||||||
int got = 0;
|
int got = 0;
|
||||||
int veid, pid, outfd, errfd, ret;
|
int veid, pid, outfd = -1, errfd = -1, ret;
|
||||||
char vpsname[OPENVZ_NAME_MAX];
|
char vpsname[OPENVZ_NAME_MAX];
|
||||||
char buf[32];
|
char buf[32];
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
@ -949,6 +949,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s\n"),
|
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s\n"),
|
||||||
errno, strerror(errno));
|
errno, strerror(errno));
|
||||||
|
|
||||||
|
vm->stdout_fd = -1;
|
||||||
|
vm->stderr_fd = -1;
|
||||||
|
|
||||||
ret = virExecNonBlock(conn, argv, &vm->pid,
|
ret = virExecNonBlock(conn, argv, &vm->pid,
|
||||||
vm->stdin_fd, &vm->stdout_fd, &vm->stderr_fd);
|
vm->stdin_fd, &vm->stdout_fd, &vm->stderr_fd);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
69
src/util.c
69
src/util.c
@ -118,6 +118,8 @@ _virExec(virConnectPtr conn,
|
|||||||
int pid, null, i;
|
int pid, null, i;
|
||||||
int pipeout[2] = {-1,-1};
|
int pipeout[2] = {-1,-1};
|
||||||
int pipeerr[2] = {-1,-1};
|
int pipeerr[2] = {-1,-1};
|
||||||
|
int childout = -1;
|
||||||
|
int childerr = -1;
|
||||||
sigset_t oldmask, newmask;
|
sigset_t oldmask, newmask;
|
||||||
struct sigaction sig_action;
|
struct sigaction sig_action;
|
||||||
|
|
||||||
@ -140,14 +142,14 @@ _virExec(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((outfd != NULL && pipe(pipeout) < 0) ||
|
if (outfd != NULL) {
|
||||||
(errfd != NULL && pipe(pipeerr) < 0)) {
|
if (*outfd == -1) {
|
||||||
|
if (pipe(pipeout) < 0) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot create pipe: %s"), strerror(errno));
|
_("cannot create pipe: %s"), strerror(errno));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outfd) {
|
|
||||||
if (non_block &&
|
if (non_block &&
|
||||||
virSetNonBlock(pipeout[0]) == -1) {
|
virSetNonBlock(pipeout[0]) == -1) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -160,19 +162,46 @@ _virExec(virConnectPtr conn,
|
|||||||
_("Failed to set close-on-exec file descriptor flag"));
|
_("Failed to set close-on-exec file descriptor flag"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
childout = pipeout[1];
|
||||||
|
} else {
|
||||||
|
childout = *outfd;
|
||||||
}
|
}
|
||||||
if (errfd) {
|
#ifndef ENABLE_DEBUG
|
||||||
|
} else {
|
||||||
|
childout = null;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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 &&
|
if (non_block &&
|
||||||
virSetNonBlock(pipeerr[0]) == -1) {
|
virSetNonBlock(pipeerr[0]) == -1) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Failed to set non-blocking file descriptor flag"));
|
_("Failed to set non-blocking file descriptor flag"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virSetCloseExec(pipeerr[0]) == -1) {
|
if (virSetCloseExec(pipeerr[0]) == -1) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Failed to set close-on-exec file descriptor flag"));
|
_("Failed to set close-on-exec file descriptor flag"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
childerr = pipeerr[1];
|
||||||
|
} else {
|
||||||
|
childerr = *errfd;
|
||||||
|
}
|
||||||
|
#ifndef ENABLE_DEBUG
|
||||||
|
} else {
|
||||||
|
childerr = null;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pid = fork()) < 0) {
|
if ((pid = fork()) < 0) {
|
||||||
@ -183,11 +212,11 @@ _virExec(virConnectPtr conn,
|
|||||||
|
|
||||||
if (pid) { /* parent */
|
if (pid) { /* parent */
|
||||||
close(null);
|
close(null);
|
||||||
if (outfd) {
|
if (outfd && *outfd == -1) {
|
||||||
close(pipeout[1]);
|
close(pipeout[1]);
|
||||||
*outfd = pipeout[0];
|
*outfd = pipeout[0];
|
||||||
}
|
}
|
||||||
if (errfd) {
|
if (errfd && *errfd == -1) {
|
||||||
close(pipeerr[1]);
|
close(pipeerr[1]);
|
||||||
*errfd = pipeerr[0];
|
*errfd = pipeerr[0];
|
||||||
}
|
}
|
||||||
@ -250,35 +279,25 @@ _virExec(virConnectPtr conn,
|
|||||||
_("failed to setup stdin file handle: %s"), strerror(errno));
|
_("failed to setup stdin file handle: %s"), strerror(errno));
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
#ifndef ENABLE_DEBUG
|
if (childout > 0 &&
|
||||||
if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0) {
|
dup2(childout, STDOUT_FILENO) < 0) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("failed to setup stdout file handle: %s"), strerror(errno));
|
_("failed to setup stdout file handle: %s"), strerror(errno));
|
||||||
_exit(1);
|
_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,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("failed to setup stderr file handle: %s"), strerror(errno));
|
_("failed to setup stderr file handle: %s"), strerror(errno));
|
||||||
_exit(1);
|
_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);
|
close(null);
|
||||||
if (pipeout[1] > 0)
|
if (childout > 0)
|
||||||
close(pipeout[1]);
|
close(childout);
|
||||||
if (pipeerr[1] > 0)
|
if (childerr > 0 &&
|
||||||
close(pipeerr[1]);
|
childerr != childout)
|
||||||
|
close(childerr);
|
||||||
|
|
||||||
execvp(argv[0], (char **) argv);
|
execvp(argv[0], (char **) argv);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user