aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-05-08 10:18:45 +0200
committerEelco Dolstra <edolstra@gmail.com>2019-05-08 10:18:45 +0200
commit92caa60c49daea807751c067c3bce96cef8399b0 (patch)
tree06eb359261f5c490018e7fde31953f20397b90eb /src
parent3e940bbf2dfdbb0f51ce84915d54750bb3dcac36 (diff)
parentfcd766097636943ff11b84747d11a4e52d3d8e38 (diff)
Merge branch 'repl/ctrlc' of https://github.com/xbreak/nix
Diffstat (limited to 'src')
-rw-r--r--src/nix/repl.cc40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index 227affc60..d8f812149 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -192,6 +192,14 @@ static int listPossibleCallback(char *s, char ***avp) {
return ac;
}
+namespace {
+ // Used to communicate to NixRepl::getLine whether a signal occurred in ::readline.
+ volatile sig_atomic_t g_signal_received = 0;
+
+ void sigintHandler(int signo) {
+ g_signal_received = signo;
+ }
+}
void NixRepl::mainLoop(const std::vector<std::string> & files)
{
@@ -251,8 +259,40 @@ void NixRepl::mainLoop(const std::vector<std::string> & files)
bool NixRepl::getLine(string & input, const std::string &prompt)
{
+ struct sigaction act, old;
+ sigset_t savedSignalMask, set;
+
+ auto setupSignals = [&]() {
+ act.sa_handler = sigintHandler;
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGINT, &act, &old))
+ throw SysError("installing handler for SIGINT");
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ if (sigprocmask(SIG_UNBLOCK, &set, &savedSignalMask))
+ throw SysError("unblocking SIGINT");
+ };
+ auto restoreSignals = [&]() {
+ if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr))
+ throw SysError("restoring signals");
+
+ if (sigaction(SIGINT, &old, 0))
+ throw SysError("restoring handler for SIGINT");
+ };
+
+ setupSignals();
char * s = readline(prompt.c_str());
Finally doFree([&]() { free(s); });
+ restoreSignals();
+
+ if (g_signal_received) {
+ g_signal_received = 0;
+ input.clear();
+ return true;
+ }
+
if (!s)
return false;
input += s;