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,8 +78,10 @@ public:
handler->flush();
}
virtual void operator()(T& item) {
if (handler.get())
if (handler.get()) {
check_for_signal();
(*handler.get())(item);
}
}
};

View file

@ -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

View file

@ -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

View file

@ -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
*/