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