allow SIGINT to interrupt infinite loops

master
Daniel Kolesa 2016-09-05 21:50:24 +02:00
parent 605efea9e2
commit fb8a793d66
2 changed files with 37 additions and 6 deletions

View File

@ -6,6 +6,7 @@
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <ostd/string.hh>
#include <ostd/maybe.hh>
@ -68,6 +69,7 @@ static ostd::Maybe<ostd::String> read_line(CsSvar *pr) {
if (!line) {
/* linenoise traps ctrl-c, detect it and let the user exit */
if (errno == EAGAIN) {
raise(SIGINT);
return ostd::nothing;
}
return ostd::String();

View File

@ -1,3 +1,5 @@
#include <signal.h>
#include <ostd/platform.hh>
#include <ostd/io.hh>
#include <ostd/string.hh>
@ -162,6 +164,38 @@ static CsCommand *get_hint_cmd(ostd::ConstCharRange buf) {
#include "tools/edit_readline.hh"
#include "tools/edit_fallback.hh"
struct InterruptedException {
};
static void do_sigint(int n) {
/* in case another SIGINT happens, terminate normally */
signal(n, SIG_DFL);
if (gcs) {
gcs->set_call_hook([]() {
gcs->set_call_hook(nullptr);
throw InterruptedException{};
});
}
}
static void do_call(CsState &cs, ostd::ConstCharRange line) {
CsValue ret;
ret.set_null();
signal(SIGINT, do_sigint);
try {
cs.run_ret(line, ret);
} catch (InterruptedException) {
signal(SIGINT, SIG_DFL);
ret.cleanup();
ostd::writeln("<execution interrupted>");
return;
}
signal(SIGINT, SIG_DFL);
if (ret.get_type() != CsValueType::null) {
ostd::writeln(ret.get_str());
}
}
static void do_tty(CsState &cs) {
auto prompt = cs.new_svar("PROMPT", "> ");
auto prompt2 = cs.new_svar("PROMPT2", ">> ");
@ -207,12 +241,7 @@ static void do_tty(CsState &cs) {
lv += line2.value();
}
add_history(lv);
CsValue ret;
ret.set_null();
cs.run_ret(lv, ret);
if (ret.get_type() != CsValueType::null) {
ostd::writeln(ret.get_str());
}
do_call(cs, lv);
if (do_exit) {
return;
}