From 863b5d814443eb791c2dd07250ac0ae29054adb0 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 4 Feb 2009 20:46:08 -0400 Subject: Added proper handling of SIGINT (C-c) and SIGPIPE (pager quits). --- src/handler.h | 4 +++- src/main.cc | 20 ++++++++++---------- src/utils.cc | 17 +++++++++++++++++ src/utils.h | 22 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/handler.h b/src/handler.h index 8f4d71b9..bfb1b08f 100644 --- a/src/handler.h +++ b/src/handler.h @@ -78,8 +78,10 @@ public: handler->flush(); } virtual void operator()(T& item) { - if (handler.get()) + if (handler.get()) { + check_for_signal(); (*handler.get())(item); + } } }; diff --git a/src/main.cc b/src/main.cc index 221374c0..06ce8563 100644 --- a/src/main.cc +++ b/src/main.cc @@ -57,11 +57,6 @@ namespace { return s; } - void sigint_handler(int sig) - { - throw std::logic_error("Interrupted by user (use Control-D to quit)"); - } - strings_list split_arguments(char * line) { strings_list args; @@ -177,12 +172,16 @@ namespace { catch (const std::exception& err) { std::cout.flush(); // first display anything that was pending - // Display any pending error context information - string context = error_context(); - if (! context.empty()) - std::cerr << context << std::endl; + if (caught_signal == NONE_CAUGHT) { + // Display any pending error context information + string context = error_context(); + if (! context.empty()) + std::cerr << context << std::endl; - std::cerr << "Error: " << err.what() << std::endl; + std::cerr << "Error: " << err.what() << std::endl; + } else { + caught_signal = NONE_CAUGHT; + } } catch (int _status) { status = _status; // used for a "quick" exit, and is used only @@ -226,6 +225,7 @@ int main(int argc, char * argv[], char * envp[]) session->option_version(*session); std::signal(SIGINT, sigint_handler); + std::signal(SIGPIPE, sigpipe_handler); #ifdef HAVE_LIBEDIT diff --git a/src/utils.cc b/src/utils.cc index 74a8ea6c..d4b05fec 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -626,6 +626,23 @@ void finish_timer(const char * name) #endif // LOGGING_ON && TIMERS_ON +/********************************************************************** + * + * Signal handlers + */ + +caught_signal_t caught_signal = NONE_CAUGHT; + +void sigint_handler(int sig) +{ + caught_signal = INTERRUPTED; +} + +void sigpipe_handler(int sig) +{ + caught_signal = PIPE_CLOSED; +} + /********************************************************************** * * General utility functions diff --git a/src/utils.h b/src/utils.h index 41142624..23ae10c7 100644 --- a/src/utils.h +++ b/src/utils.h @@ -475,6 +475,28 @@ void finish_timer(const char * name); #include "stream.h" #include "pushvar.h" +enum caught_signal_t { + NONE_CAUGHT, + INTERRUPTED, + PIPE_CLOSED +}; + +extern caught_signal_t caught_signal; + +void sigint_handler(int sig); +void sigpipe_handler(int sig); + +inline void check_for_signal() { + switch (caught_signal) { + case NONE_CAUGHT: + break; + case INTERRUPTED: + throw std::runtime_error("Interrupted by user (use Control-D to quit)"); + case PIPE_CLOSED: + throw std::runtime_error("Pipe terminated"); + } +} + /** * @name General utility functions */ -- cgit v1.2.3