Extend virCommandProcessIO to include the send buffers in the poll loop. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> --- src/util/vircommand.c | 62 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/util/vircommand.c b/src/util/vircommand.c index bb9ecdf348..976231444e 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -1815,6 +1815,61 @@ virCommandSetSendBuffer(virCommandPtr cmd, } +static int +virCommandSendBuffersFillPollfd(virCommandPtr cmd, + struct pollfd *fds, + int startidx) +{ + size_t i, j; + + for (i = 0, j = 0; i < virCommandGetNumSendBuffers(cmd); i++) { + if (cmd->sendBuffers[i].fd >= 0) { + fds[startidx + j].fd = cmd->sendBuffers[i].fd; + fds[startidx + j].events = POLLOUT; + fds[startidx + j].revents = 0; + j++; + } + } + + return j; +} + + +static int +virCommandSendBuffersHandlePoll(virCommandPtr cmd, + struct pollfd *fds) +{ + size_t i; + int done; + + for (i = 0; i < virCommandGetNumSendBuffers(cmd); i++) { + if (fds->fd == cmd->sendBuffers[i].fd) + break; + } + if (i == virCommandGetNumSendBuffers(cmd)) + return 0; + + done = write(fds->fd, + cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset, + cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset); + if (done < 0) { + if (errno == EPIPE) { + VIR_DEBUG("child closed PIPE early, ignoring EPIPE " + "on fd %d", cmd->sendBuffers[i].fd); + VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd); + } else if (errno != EINTR && errno != EAGAIN) { + virReportSystemError(errno, "%s", + _("unable to write to child input")); + return -1; + } + } else { + cmd->sendBuffers[i].offset += done; + if (cmd->sendBuffers[i].offset == cmd->sendBuffers[i].buflen) + VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd); + } + return 0; +} + /** * virCommandSetInputBuffer: * @cmd: the command to modify @@ -2169,7 +2224,7 @@ virCommandProcessIO(virCommandPtr cmd) goto cleanup; ret = -1; - if (VIR_ALLOC_N(fds, 3) < 0) + if (VIR_ALLOC_N(fds, 3 + virCommandGetNumSendBuffers(cmd)) < 0) goto cleanup; for (;;) { @@ -2195,6 +2250,8 @@ virCommandProcessIO(virCommandPtr cmd) nfds++; } + nfds += virCommandSendBuffersFillPollfd(cmd, fds, nfds); + if (nfds == 0) break; @@ -2267,6 +2324,9 @@ virCommandProcessIO(virCommandPtr cmd) if (inoff == inlen) VIR_FORCE_CLOSE(cmd->inpipe); } + } else if (fds[i].revents & (POLLOUT | POLLHUP | POLLERR)) { + if (virCommandSendBuffersHandlePoll(cmd, &fds[i]) < 0) + goto cleanup; } } } -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list