Eliminate fish_key_reader signal handlers

They call wgettext, wfprintf, etc. and are so wildly unsafe.
This commit is contained in:
ridiculousfish 2020-02-13 00:33:39 -08:00
parent 6cccfa7cf4
commit 89644911a1

View File

@ -43,7 +43,6 @@ static const wchar_t *ctrl_symbolic_names[] = {
L"\\b", L"\\t", L"\\n", L"\\v", L"\\f", L"\\r", nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, L"\\e", nullptr, nullptr, nullptr, nullptr};
static bool keep_running = true;
/// Return true if the recent sequence of characters indicates the user wants to exit the program.
static bool should_exit(wchar_t wc) {
@ -205,7 +204,7 @@ static void process_input(bool continuous_mode) {
std::vector<wchar_t> bind_chars;
std::fwprintf(stderr, L"Press a key\n\n");
while (keep_running) {
for (;;) {
char_event_t evt{0};
if (reader_test_and_clear_interrupted()) {
evt = char_event_t{shell_modes.c_cc[VINTR]};
@ -242,56 +241,19 @@ static void process_input(bool continuous_mode) {
}
}
/// Make sure we cleanup before exiting if we receive a signal that should cause us to exit.
/// Otherwise just report receipt of the signal.
static struct sigaction old_sigactions[32];
static void signal_handler(int signo, siginfo_t *siginfo, void *siginfo_arg) {
std::fwprintf(stdout, _(L"signal #%d (%ls) received\n"), signo, sig2wcs(signo));
if (signo == SIGHUP || signo == SIGTERM || signo == SIGABRT || signo == SIGSEGV) {
keep_running = false;
}
if (old_sigactions[signo].sa_handler != SIG_IGN &&
old_sigactions[signo].sa_handler != SIG_DFL) {
int needs_siginfo = old_sigactions[signo].sa_flags & SA_SIGINFO;
if (needs_siginfo) {
old_sigactions[signo].sa_sigaction(signo, siginfo, siginfo_arg);
} else {
old_sigactions[signo].sa_handler(signo);
}
}
}
/// Install a handler for every signal. This allows us to restore the tty modes so the terminal is
/// still usable when we die. If the signal already has a handler arrange to invoke it from within
/// our handler.
static void install_our_signal_handlers() {
struct sigaction new_sa, old_sa;
sigemptyset(&new_sa.sa_mask);
new_sa.sa_flags = SA_SIGINFO;
new_sa.sa_sigaction = signal_handler;
for (int signo = 1; signo < 32; signo++) {
if (sigaction(signo, &new_sa, &old_sa) != -1) {
std::memcpy(&old_sigactions[signo], &old_sa, sizeof(old_sa));
}
}
}
/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment.
static void setup_and_process_keys(bool continuous_mode) {
set_interactive_session(
session_interactivity_t::implied); // by definition this program is interactive
set_interactive_session(session_interactivity_t::implied);
set_main_thread();
setup_fork_guards();
env_init();
reader_init();
parser_t &parser = parser_t::principal_parser();
scoped_push<bool> interactive{&parser.libdata().is_interactive, true};
signal_set_handlers(true);
// We need to set the shell-modes for ICRNL,
// in fish-proper this is done once a command is run.
tcsetattr(STDIN_FILENO, TCSANOW, &shell_modes);
install_our_signal_handlers();
if (continuous_mode) {
std::fwprintf(stderr, L"\n");
@ -304,7 +266,7 @@ static void setup_and_process_keys(bool continuous_mode) {
process_input(continuous_mode);
restore_term_mode();
restore_term_foreground_process_group();
_exit(0);
}
static bool parse_debug_level_flag() {
@ -400,5 +362,6 @@ int main(int argc, char **argv) {
}
setup_and_process_keys(continuous_mode);
return 0;
exit_without_destructors(0);
return EXIT_FAILURE; // above should exit
}