[libvirt] [PATCH 3/3]: Read cmd stdout + stderr in virRun
Daniel P. Berrange
berrange at redhat.com
Mon Nov 3 11:51:51 UTC 2008
On Thu, Oct 30, 2008 at 02:06:35PM -0400, Cole Robinson wrote:
> The attached patch is my second cut at reading
> stdout and stderr of the command virRun kicks
> off. There is no hard limit to the amount of
> data we read now, and we use a poll loop to
> avoid any possible full buffer issues.
>
> If stdout or stderr had any content, we DEBUG
> it, and if the command appears to fail we
> return stderr in the error message. So now,
> trying to stop a logical pool with active
> volumes will return:
>
> $ sudo virsh pool-destroy vgdata
> libvir: error : internal error '/sbin/vgchange -an vgdata' exited with non-zero status 5 and signal 0: Can't deactivate volume group "vgdata" with 2 open logical volume(s)
> error: Failed to destroy pool vgdata
> + 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;
> + }
>
> - while ((ret = waitpid(childpid, &exitstatus, 0) == -1) && errno == EINTR);
> - if (ret == -1) {
> + 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, "%s", "realloc buf");
> + 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;
> + }
I think it'd be nice to move the I/O processing loop out of the
virRun() function and into a separate helper functiion along the
lines of
virPipeReadUntilEOF(int outfd, int errfd, char **outbuf, char **errbuf)
Daniel
--
|: 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 :|
More information about the libvir-list
mailing list