Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make output_stream_t::append() fallible and handle SIGINT on append #9266

Closed
wants to merge 3 commits into from

Conversation

mqudsi
Copy link
Contributor

@mqudsi mqudsi commented Oct 8, 2022

This patch series addresses a long-standing issue (output_stream_t::append() is assumed to never fail and returns void) that made it difficult to handle output termination via Ctrl-C (by halting progress and ending early) for various builtins with lots of output, history being the best example because it wrote to the pager (giving the user plenty of time and reason to Ctrl-C the running process, but to no effect besides an error message).


Make output_stream_t::append() fallible

Allow errors encountered by certain implementations of output_stream_t when
writing to the output sink to be bubbled back to the caller.

Silently handle fd_output_stream_t append errors in case of SIGINT

If EINTR caused by SIGINT is encountered while writing to the
fd_output_stream_t output fd, mark the output stream as errored and return
false to the caller but do not visibly complain.

Addressing the outstanding TODO notwithstanding, this is needed to avoid
littering the tty with spurious errors when the user hits Ctrl-C to abort a
long-running builtin's output (w/ the primary example being history).

history: Handle Ctrl-C/SIGINT or other errors on output append

When there are multiple screens worth of output and history is writing to the
pager, pressing Ctrl-C at the end of a screen doesn't exit the pager (q is
needed for that) but previously caused fish to emit an error ("write:
Interrupted system call) until we started silently handling SIGINT in
fd_output_stream_t::append().

This patch makes history detect when the append() call returns with an error
and causes it to end early rather than repeatedly trying (and failing) to write
to the output stream.

src/io.cpp Outdated Show resolved Hide resolved
src/io.cpp Outdated Show resolved Hide resolved
// output stream as errored, causing us to both return false and skip any future writes.
// We're currently going with the latter, especially seeing as no callers currently
// check the result of `append()` (since it was always a void function before).
} else if (errno != EPIPE) {
wperror(L"write");
}
errored_ = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any cases where we *shouldn'*t error?

E.g. if we get EINTR for other signals? EAGAIN?

This now is quite eager to stop writing and I'm scared.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now is quite eager to stop writing and I'm scared.

The behavior hasn't changed. It always set errored_ = true; in case of EINTR but now we just don't call wperror(..) before doing so.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, you're right, now I'm confused as to why I've never seen an error for EINTR being printed here.

Allow errors encountered by certain implementations of `output_stream_t` when
writing to the output sink to be bubbled back to the caller.
mqudsi added 2 commits October 8, 2022 13:23
If EINTR caused by SIGINT is encountered while writing to the
`fd_output_stream_t` output fd, mark the output stream as errored and return
false to the caller but do not visibly complain.

Addressing the outstanding TODO notwithstanding, this is needed to avoid
littering the tty with spurious errors when the user hits Ctrl-C to abort a
long-running builtin's output (w/ the primary example being `history`).
When there are multiple screens worth of output and `history` is writing to the
pager, pressing Ctrl-C at the end of a screen doesn't exit the pager (`q` is
needed for that) but previously caused fish to emit an error ("write:
Interrupted system call) until we starting silently handling SIGINT in
`fd_output_stream_t::append()`.

This patch makes `history` detect when the `append()` call returns with an error
and causes it to end early rather than repeatedly trying (and failing) to write
to the output stream.
// the return value and skip future calls to `append()`) or we can flag the entire
// output stream as errored, causing us to both return false and skip any future writes.
// We're currently going with the latter, especially seeing as no callers currently
// check the result of `append()` (since it was always a void function before).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can flag the entire output stream as errored, causing us to both return false and skip any future writes.

I guess for EINTR that's somewhat implied because SIGINT cancels builtin execution.

}

// We are intentionally not returning false in case of an output error, as the user aborting the
// output early (the most common case) isn't a reason to exit w/ a non-zero status code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.. but in this case we likely exit with a non-zero signal code like SIGINT = 130

// Don't force an error if output was aborted (typically via Ctrl-C/SIGINT); just don't
// try writing any more.
output_error = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

history is the worst offender (can't seem to hit the wperror("write") on Linux though).
There are probably more cases where we could stop writing early (string repeat) etc.

Anyway, this seems like a good step forward, LGTM!

@mqudsi mqudsi added this to the fish 3.6.0 milestone Oct 16, 2022
@mqudsi mqudsi closed this in 410b4c0 Oct 16, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants