mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-13 11:15:08 +00:00
Log stdout and stderr in virRun
This commit is contained in:
parent
a9a11b5393
commit
3796e5802f
@ -1,3 +1,7 @@
|
|||||||
|
Wed Nov 5 13:56:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
|
* src/util.c: Log stdout and stderr in virRun
|
||||||
|
|
||||||
Wed Nov 5 13:39:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
Wed Nov 5 13:39:00 EST 2008 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
* src/util.c: Log the argv passed to virExec and virRun
|
* src/util.c: Log the argv passed to virExec and virRun
|
||||||
|
138
src/util.c
138
src/util.c
@ -31,6 +31,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#if HAVE_SYS_WAIT_H
|
#if HAVE_SYS_WAIT_H
|
||||||
@ -414,6 +415,86 @@ virExec(virConnectPtr conn,
|
|||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virPipeReadUntilEOF(virConnectPtr conn, int outfd, int errfd,
|
||||||
|
char **outbuf, char **errbuf) {
|
||||||
|
|
||||||
|
struct pollfd fds[2];
|
||||||
|
int i;
|
||||||
|
int finished[2];
|
||||||
|
|
||||||
|
fds[0].fd = outfd;
|
||||||
|
fds[0].events = POLLIN;
|
||||||
|
finished[0] = 0;
|
||||||
|
fds[1].fd = errfd;
|
||||||
|
fds[1].events = POLLIN;
|
||||||
|
finished[1] = 0;
|
||||||
|
|
||||||
|
while(!(finished[0] && finished[1])) {
|
||||||
|
|
||||||
|
if (poll(fds, ARRAY_CARDINALITY(fds), -1) < 0) {
|
||||||
|
if (errno == EAGAIN)
|
||||||
|
continue;
|
||||||
|
goto pollerr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_CARDINALITY(fds); ++i) {
|
||||||
|
char data[1024], **buf;
|
||||||
|
int got, size;
|
||||||
|
|
||||||
|
if (!(fds[i].revents))
|
||||||
|
continue;
|
||||||
|
else if (fds[i].revents & POLLHUP)
|
||||||
|
finished[i] = 1;
|
||||||
|
|
||||||
|
if (!(fds[i].revents & POLLIN)) {
|
||||||
|
if (fds[i].revents & POLLHUP)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("Unknown poll response."));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
got = read(fds[i].fd, data, sizeof(data));
|
||||||
|
|
||||||
|
if (got == 0) {
|
||||||
|
finished[i] = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (got < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
if (errno == EAGAIN)
|
||||||
|
break;
|
||||||
|
goto pollerr;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = ((fds[i].fd == outfd) ? outbuf : errbuf);
|
||||||
|
size = (*buf ? strlen(*buf) : 0);
|
||||||
|
if (VIR_REALLOC_N(*buf, size+got+1) < 0) {
|
||||||
|
ReportError(conn, VIR_ERR_NO_MEMORY, NULL);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memmove(*buf+size, data, got);
|
||||||
|
(*buf)[size+got] = '\0';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pollerr:
|
||||||
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("poll error: %s"), strerror(errno));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
VIR_FREE(*outbuf);
|
||||||
|
VIR_FREE(*errbuf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @conn connection to report errors against
|
* @conn connection to report errors against
|
||||||
* @argv NULL terminated argv to run
|
* @argv NULL terminated argv to run
|
||||||
@ -433,43 +514,66 @@ int
|
|||||||
virRun(virConnectPtr conn,
|
virRun(virConnectPtr conn,
|
||||||
const char *const*argv,
|
const char *const*argv,
|
||||||
int *status) {
|
int *status) {
|
||||||
int childpid, exitstatus, ret;
|
int childpid, exitstatus, execret, waitret;
|
||||||
char *argv_str;
|
int ret = -1;
|
||||||
|
int errfd = -1, outfd = -1;
|
||||||
|
char *outbuf = NULL;
|
||||||
|
char *errbuf = NULL;
|
||||||
|
char *argv_str = NULL;
|
||||||
|
|
||||||
if ((argv_str = virArgvToString(argv)) == NULL) {
|
if ((argv_str = virArgvToString(argv)) == NULL) {
|
||||||
ReportError(conn, VIR_ERR_NO_MEMORY, _("command debug string"));
|
ReportError(conn, VIR_ERR_NO_MEMORY, _("command debug string"));
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
DEBUG0(argv_str);
|
DEBUG0(argv_str);
|
||||||
VIR_FREE(argv_str);
|
|
||||||
|
|
||||||
if ((ret = __virExec(conn, argv, NULL, NULL,
|
if ((execret = __virExec(conn, argv, NULL, NULL,
|
||||||
&childpid, -1, NULL, NULL, VIR_EXEC_NONE)) < 0)
|
&childpid, -1, &outfd, &errfd,
|
||||||
return ret;
|
VIR_EXEC_NONE)) < 0) {
|
||||||
|
ret = execret;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
while ((ret = waitpid(childpid, &exitstatus, 0) == -1) && errno == EINTR);
|
if (virPipeReadUntilEOF(conn, outfd, errfd, &outbuf, &errbuf) < 0)
|
||||||
if (ret == -1) {
|
goto error;
|
||||||
|
|
||||||
|
if (outbuf)
|
||||||
|
DEBUG("Command stdout: %s", outbuf);
|
||||||
|
if (errbuf)
|
||||||
|
DEBUG("Command stderr: %s", errbuf);
|
||||||
|
|
||||||
|
while ((waitret = waitpid(childpid, &exitstatus, 0) == -1) &&
|
||||||
|
errno == EINTR);
|
||||||
|
if (waitret == -1) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot wait for '%s': %s"),
|
_("cannot wait for '%s': %s"),
|
||||||
argv[0], strerror(errno));
|
argv[0], strerror(errno));
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == NULL) {
|
if (status == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
if (WIFEXITED(exitstatus) && WEXITSTATUS(exitstatus) == 0)
|
if (WIFEXITED(exitstatus) && WEXITSTATUS(exitstatus) != 0) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("%s exited with non-zero status %d and signal %d"),
|
_("'%s' exited with non-zero status %d and "
|
||||||
argv[0],
|
"signal %d: %s"), argv_str,
|
||||||
WIFEXITED(exitstatus) ? WEXITSTATUS(exitstatus) : 0,
|
WIFEXITED(exitstatus) ? WEXITSTATUS(exitstatus) : 0,
|
||||||
WIFSIGNALED(exitstatus) ? WTERMSIG(exitstatus) : 0);
|
WIFSIGNALED(exitstatus) ? WTERMSIG(exitstatus) : 0,
|
||||||
return -1;
|
(errbuf ? errbuf : ""));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*status = exitstatus;
|
*status = exitstatus;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
VIR_FREE(outbuf);
|
||||||
|
VIR_FREE(errbuf);
|
||||||
|
VIR_FREE(argv_str);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* __MINGW32__ */
|
#else /* __MINGW32__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user