Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> --- src/util/vircommand.c | 70 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/util/vircommand.c b/src/util/vircommand.c index 0e367eeeab..357a9888a1 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -1803,6 +1803,69 @@ virCommandSetSendBuffer(virCommandPtr cmd, } +static int +virCommandGetNumSendBuffers(virCommandPtr cmd) +{ + return cmd->numSendBuffers; +} + + +static int +virCommandAddSendBuffersFillPollfd(virCommandPtr cmd, + struct pollfd *fds, + int startidx) +{ + size_t i, j; + + for (i = 0, j = 0; i < cmd->numSendBuffers; 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 < cmd->numSendBuffers; i++) { + if (fds->fd == cmd->sendBuffers[i].fd) + break; + } + if (i == cmd->numSendBuffers) + return 0; + + done = write(fds->fd, + cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset, + MIN(cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset, + MAX_PIPE_FEED_BYTES)); + 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 @@ -2157,7 +2220,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 (;;) { @@ -2183,6 +2246,8 @@ virCommandProcessIO(virCommandPtr cmd) nfds++; } + nfds += virCommandAddSendBuffersFillPollfd(cmd, fds, nfds); + if (nfds == 0) break; @@ -2255,6 +2320,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