summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-02-04 20:46:08 -0400
committerJohn Wiegley <johnw@newartisans.com>2009-02-04 20:46:08 -0400
commit863b5d814443eb791c2dd07250ac0ae29054adb0 (patch)
treec7c1f0e284c4589c510d8d1efedc18045481bedd /src
parent04ac5ffcb4ae27ad85f9ab31227d16770d8f7e6e (diff)
downloadfork-ledger-863b5d814443eb791c2dd07250ac0ae29054adb0.tar.gz
fork-ledger-863b5d814443eb791c2dd07250ac0ae29054adb0.tar.bz2
fork-ledger-863b5d814443eb791c2dd07250ac0ae29054adb0.zip
Added proper handling of SIGINT (C-c) and SIGPIPE (pager quits).
Diffstat (limited to 'src')
-rw-r--r--src/handler.h4
-rw-r--r--src/main.cc20
-rw-r--r--src/utils.cc17
-rw-r--r--src/utils.h22
4 files changed, 52 insertions, 11 deletions
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
@@ -628,6 +628,23 @@ void finish_timer(const char * name)
/**********************************************************************
*
+ * 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
*/