break;
if (poll(fds, nfds, -1) < 0) {
- if ((errno == EAGAIN) || (errno == EINTR))
+ if (errno == EAGAIN || errno == EINTR)
continue;
virReportSystemError(errno, "%s",
_("unable to poll on child"));
done = write(infd, cmd->inbuf + inoff,
inlen - inoff);
if (done < 0) {
- if (errno != EINTR &&
- errno != EAGAIN) {
+ if (errno == EPIPE) {
+ VIR_DEBUG("child closed stdin early, ignoring EPIPE "
+ "on fd %d", infd);
+ if (VIR_CLOSE(*inpipe) < 0)
+ VIR_DEBUG("ignoring failed close on fd %d", infd);
+ infd = -1;
+ } else if (errno != EINTR && errno != EAGAIN) {
virReportSystemError(errno, "%s",
_("unable to write to child input"));
goto cleanup;
bool string_io;
bool async_io = false;
char *str;
+ int tmpfd;
if (!cmd ||cmd->has_error == ENOMEM) {
virReportOOMError();
cmd->flags |= VIR_EXEC_RUN_SYNC;
if (virCommandRunAsync(cmd, NULL) < 0) {
if (cmd->inbuf) {
- int tmpfd = infd[0];
+ tmpfd = infd[0];
if (VIR_CLOSE(infd[0]) < 0)
VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
tmpfd = infd[1];
return -1;
}
+ tmpfd = infd[0];
+ if (VIR_CLOSE(infd[0]) < 0)
+ VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
if (string_io)
ret = virCommandProcessIO(cmd, &infd[1]);
/* Reset any capturing, in case caller runs
* this identical command again */
if (cmd->inbuf) {
- int tmpfd = infd[0];
- if (VIR_CLOSE(infd[0]) < 0)
- VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
tmpfd = infd[1];
if (VIR_CLOSE(infd[1]) < 0)
VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
}
if (cmd->outbuf == &outbuf) {
- int tmpfd ATTRIBUTE_UNUSED;
tmpfd = cmd->outfd;
if (VIR_CLOSE(cmd->outfd) < 0)
VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
VIR_FREE(outbuf);
}
if (cmd->errbuf == &errbuf) {
- int tmpfd ATTRIBUTE_UNUSED;
tmpfd = cmd->errfd;
if (VIR_CLOSE(cmd->errfd) < 0)
VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
#include "command.h"
#include "virfile.h"
#include "virpidfile.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
#ifdef WIN32
return ret;
}
+/*
+ * Run program, no args, inherit all ENV, keep CWD.
+ * Ignore huge stdin data, to provoke SIGPIPE or EPIPE in parent.
+ */
+static int test20(const void *unused ATTRIBUTE_UNUSED)
+{
+ virCommandPtr cmd = virCommandNewArgList(abs_builddir "/commandhelper",
+ "--close-stdin", NULL);
+ char *buf;
+ int ret = -1;
+
+ struct sigaction sig_action;
+
+ sig_action.sa_handler = SIG_IGN;
+ sig_action.sa_flags = 0;
+ sigemptyset(&sig_action.sa_mask);
+
+ sigaction(SIGPIPE, &sig_action, NULL);
+
+ if (virAsprintf(&buf, "1\n%100000d\n", 2) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ virCommandSetInputBuffer(cmd, buf);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virErrorPtr err = virGetLastError();
+ printf("Cannot run child %s\n", err->message);
+ goto cleanup;
+ }
+
+ ret = checkoutput("test20");
+cleanup:
+ virCommandFree(cmd);
+ VIR_FREE(buf);
+ return ret;
+}
+
static const char *const newenv[] = {
"PATH=/usr/bin:/bin",
"HOSTNAME=test",
DO_TEST(test17);
DO_TEST(test18);
DO_TEST(test19);
+ DO_TEST(test20);
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}