fdstream: don't raise error on SIGPIPE if abort requested

The iohelper dies on SIGPIPE if the stream is closed before all data
is processed. IMO this should be an error condition for virStreamFinish
according to docs like:

  * This method is a synchronization point for all asynchronous
  * errors, so if this returns a success code the application can
  * be sure that all data has been successfully processed.

However for virStreamAbort, not so much:

  * Request that the in progress data transfer be cancelled
  * abnormally before the end of the stream has been reached.
  * For output streams this can be used to inform the driver
  * that the stream is being terminated early. For input
  * streams this can be used to inform the driver that it
  * should stop sending data.

Without this, virStreamAbort will realistically always error for
active streams like domain console. So, treat the SIGPIPE case
as non-fatal if abort is requested.

Note, this will only affect an explicit user requested abort. An
abnormal abort, like from a server error, always raises an error
in the daemon.
This commit is contained in:
Cole Robinson 2016-04-25 14:00:58 -04:00
parent 66a03d0af2
commit a5481546d6

View File

@ -242,7 +242,7 @@ virFDStreamAddCallback(virStreamPtr st,
}
static int
virFDStreamCloseCommand(struct virFDStreamData *fdst)
virFDStreamCloseCommand(struct virFDStreamData *fdst, bool streamAbort)
{
char buf[1024];
ssize_t len;
@ -265,6 +265,12 @@ virFDStreamCloseCommand(struct virFDStreamData *fdst)
if (buf[0] != '\0') {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", buf);
} else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGPIPE) {
if (streamAbort) {
/* Explicit abort request means the caller doesn't care
if there's data left over, so skip the error */
goto out;
}
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("I/O helper exited "
"before all data was processed"));
@ -278,6 +284,7 @@ virFDStreamCloseCommand(struct virFDStreamData *fdst)
goto cleanup;
}
out:
ret = 0;
cleanup:
virCommandFree(fdst->cmd);
@ -329,7 +336,7 @@ virFDStreamCloseInt(virStreamPtr st, bool streamAbort)
/* mutex locked */
ret = VIR_CLOSE(fdst->fd);
if (virFDStreamCloseCommand(fdst) < 0)
if (virFDStreamCloseCommand(fdst, streamAbort) < 0)
ret = -1;
if (VIR_CLOSE(fdst->errfd) < 0)