diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2019-05-08 10:18:45 +0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2019-05-08 10:18:45 +0200 |
commit | 92caa60c49daea807751c067c3bce96cef8399b0 (patch) | |
tree | 06eb359261f5c490018e7fde31953f20397b90eb /src | |
parent | 3e940bbf2dfdbb0f51ce84915d54750bb3dcac36 (diff) | |
parent | fcd766097636943ff11b84747d11a4e52d3d8e38 (diff) |
Merge branch 'repl/ctrlc' of https://github.com/xbreak/nix
Diffstat (limited to 'src')
-rw-r--r-- | src/nix/repl.cc | 40 |
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; |