diff --git a/input.cpp b/input.cpp index 5c178be8d..7ef8402a1 100644 --- a/input.cpp +++ b/input.cpp @@ -507,7 +507,7 @@ wint_t input_readch() /* Clear the interrupted flag */ - reader_interrupted(); + reader_reset_interrupted(); /* Search for sequence in mapping tables diff --git a/reader.cpp b/reader.cpp index f90df311f..b7d531125 100644 --- a/reader.cpp +++ b/reader.cpp @@ -323,6 +323,9 @@ public: /** Whether a screen reset is needed after a repaint. */ bool screen_reset_needed; + /** Whether the reader should exit on ^C. */ + bool interruptible; + /** Constructor */ reader_data_t() : allow_autosuggestion(0), @@ -339,7 +342,8 @@ public: next(0), search_mode(0), repaint_needed(0), - screen_reset_needed(0) + screen_reset_needed(0), + interruptible(0) { } }; @@ -373,7 +377,7 @@ static pid_t original_pid; /** This variable is set to true by the signal handler when ^C is pressed */ -static int interrupted=0; +static volatile int interrupted=0; /* @@ -632,11 +636,23 @@ static void remove_duplicates(std::vector &l) l.erase(std::unique(l.begin(), l.end()), l.end()); } + +void reader_reset_interrupted() +{ + interrupted = 0; +} + int reader_interrupted() { int res=interrupted; if (res) + { interrupted=0; + } + if (res && data && data->interruptible) + { + reader_exit(1, 0); + } return res; } @@ -2380,6 +2396,11 @@ void reader_set_test_function(int (*f)(const wchar_t *)) data->test_func = f; } +void reader_set_interruptible(bool i) +{ + data->interruptible = i; +} + void reader_import_history_if_necessary(void) { /* Import history from bash, etc. if our current history is empty */ diff --git a/reader.h b/reader.h index ba024e865..f94d8a896 100644 --- a/reader.h +++ b/reader.h @@ -111,9 +111,18 @@ void reader_set_buffer(const wcstring &b, size_t p); */ size_t reader_get_cursor_pos(); +/** + Clear the interrupted flag unconditionally without handling anything. The + flag could have been set e.g. when an interrupt arrived just as we were + ending an earlier \c reader_readline invocation but before the + \c is_interactive_read flag was cleared. +*/ +void reader_reset_interrupted(); + /** Return the value of the interrupted flag, which is set by the sigint - handler, and clear it if it was set. + handler, and clear it if it was set. If the current reader is interruptible, + call \c reader_exit(). */ int reader_interrupted(); @@ -181,6 +190,9 @@ void reader_set_right_prompt(const wcstring &prompt); /** Sets whether autosuggesting is allowed. */ void reader_set_allow_autosuggesting(bool flag); +/** Sets whether the reader should exit on ^C. */ +void reader_set_interruptible(bool flag); + /** Returns true if the shell is exiting, 0 otherwise. */