From 920ded26b9d0d0adca52826d4dc8cd02a7f2b83c Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Sat, 8 Oct 2022 12:30:17 -0500 Subject: [PATCH] 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 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. --- src/history.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/history.cpp b/src/history.cpp index 41735bfcd..9ab51723c 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1482,8 +1482,10 @@ bool history_t::search(history_search_type_t search_type, const wcstring_list_t wcstring_list_t collected; wcstring formatted_record; size_t remaining = max_items; + bool output_error = false; - // The function we use to act on each item. + // The function we use to act on each item. The return value indicates whether the search should + // continue (true) or stop (on false). std::function func = [&](const history_item_t &item) -> bool { if (remaining == 0) return false; remaining -= 1; @@ -1493,7 +1495,11 @@ bool history_t::search(history_search_type_t search_type, const wcstring_list_t collected.push_back(std::move(formatted_record)); } else { // We can output this immediately. - streams.out.append(formatted_record); + if (!streams.out.append(formatted_record)) { + // This can happen if the user hit Ctrl-C to abort (maybe after the first page?). + output_error = true; + return false; + } } return true; }; @@ -1514,9 +1520,16 @@ bool history_t::search(history_search_type_t search_type, const wcstring_list_t } // Output any items we collected (which only happens in reverse). - for (auto iter = collected.rbegin(); iter != collected.rend(); ++iter) { - streams.out.append(*iter); + for (auto iter = collected.rbegin(); !output_error && iter != collected.rend(); ++iter) { + if (!streams.out.append(*iter)) { + // Don't force an error if output was aborted (typically via Ctrl-C/SIGINT); just don't + // try writing any more. + output_error = true; + } } + + // 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. return true; }