Added proper handling of SIGINT (C-c) and SIGPIPE (pager quits).

This commit is contained in:
John Wiegley 2009-02-04 20:46:08 -04:00
parent 04ac5ffcb4
commit 863b5d8144
4 changed files with 52 additions and 11 deletions

View file

@ -78,9 +78,11 @@ public:
handler->flush(); handler->flush();
} }
virtual void operator()(T& item) { virtual void operator()(T& item) {
if (handler.get()) if (handler.get()) {
check_for_signal();
(*handler.get())(item); (*handler.get())(item);
} }
}
}; };
typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr; typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr;

View file

@ -57,11 +57,6 @@ namespace {
return s; 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 split_arguments(char * line)
{ {
strings_list args; strings_list args;
@ -177,12 +172,16 @@ namespace {
catch (const std::exception& err) { catch (const std::exception& err) {
std::cout.flush(); // first display anything that was pending std::cout.flush(); // first display anything that was pending
if (caught_signal == NONE_CAUGHT) {
// Display any pending error context information // Display any pending error context information
string context = error_context(); string context = error_context();
if (! context.empty()) if (! context.empty())
std::cerr << context << std::endl; 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) { catch (int _status) {
status = _status; // used for a "quick" exit, and is used only 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); session->option_version(*session);
std::signal(SIGINT, sigint_handler); std::signal(SIGINT, sigint_handler);
std::signal(SIGPIPE, sigpipe_handler);
#ifdef HAVE_LIBEDIT #ifdef HAVE_LIBEDIT

View file

@ -626,6 +626,23 @@ void finish_timer(const char * name)
#endif // LOGGING_ON && TIMERS_ON #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 * General utility functions

View file

@ -475,6 +475,28 @@ void finish_timer(const char * name);
#include "stream.h" #include "stream.h"
#include "pushvar.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 * @name General utility functions
*/ */