mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-26 12:37:06 +08:00
Do not throw SIGINT after catching SIGINT signal (#128)
This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/117
This commit is contained in:
parent
1fc86d31db
commit
93922f102f
@ -226,6 +226,7 @@ if (FTXUI_BUILD_TESTS AND ${CMAKE_VERSION} VERSION_GREATER "3.11.4")
|
|||||||
src/ftxui/component/input_test.cpp
|
src/ftxui/component/input_test.cpp
|
||||||
src/ftxui/component/radiobox_test.cpp
|
src/ftxui/component/radiobox_test.cpp
|
||||||
src/ftxui/component/receiver_test.cpp
|
src/ftxui/component/receiver_test.cpp
|
||||||
|
src/ftxui/component/screen_interactive_test.cpp
|
||||||
src/ftxui/component/terminal_input_parser_test.cpp
|
src/ftxui/component/terminal_input_parser_test.cpp
|
||||||
src/ftxui/component/toggle_test.cpp
|
src/ftxui/component/toggle_test.cpp
|
||||||
src/ftxui/dom/gauge_test.cpp
|
src/ftxui/dom/gauge_test.cpp
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <stdio.h> // for fileno, stdin
|
#include <stdio.h> // for fileno, stdin
|
||||||
#include <algorithm> // for copy, max, min
|
#include <algorithm> // for copy, max, min
|
||||||
#include <csignal> // for signal, SIGINT, SIGWINCH
|
#include <csignal> // for signal, SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIGWINCH
|
||||||
#include <cstdlib> // for exit, NULL
|
#include <cstdlib> // for NULL
|
||||||
|
#include <initializer_list> // for initializer_list
|
||||||
#include <iostream> // for cout, ostream, basic_ostream, operator<<, endl, flush
|
#include <iostream> // for cout, ostream, basic_ostream, operator<<, endl, flush
|
||||||
#include <stack> // for stack
|
#include <stack> // for stack
|
||||||
#include <thread> // for thread
|
#include <thread> // for thread
|
||||||
@ -12,7 +13,7 @@
|
|||||||
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/event.hpp" // for Event
|
#include "ftxui/component/event.hpp" // for Event
|
||||||
#include "ftxui/component/mouse.hpp" // for Mouse
|
#include "ftxui/component/mouse.hpp" // for Mouse
|
||||||
#include "ftxui/component/receiver.hpp" // for ReceiverImpl, SenderImpl, MakeReceiver
|
#include "ftxui/component/receiver.hpp" // for ReceiverImpl, MakeReceiver, Sender, SenderImpl, Receiver
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
#include "ftxui/component/screen_interactive.hpp"
|
||||||
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputParser
|
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputParser
|
||||||
#include "ftxui/dom/node.hpp" // for Node, Render
|
#include "ftxui/dom/node.hpp" // for Node, Render
|
||||||
@ -31,8 +32,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <sys/select.h> // for select, FD_ISSET, FD_SET, FD_ZERO, fd_set
|
#include <sys/select.h> // for select, FD_ISSET, FD_SET, FD_ZERO, fd_set
|
||||||
#include <termios.h> // for tcsetattr, tcgetattr, cc_t
|
#include <termios.h> // for tcsetattr, termios, tcgetattr, TCSANOW, cc_t, ECHO, ICANON, VMIN, VTIME
|
||||||
#include <unistd.h> // for STDIN_FILENO, read
|
#include <unistd.h> // for STDIN_FILENO, read
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Quick exit is missing in standard CLang headers
|
// Quick exit is missing in standard CLang headers
|
||||||
@ -201,12 +202,11 @@ const std::string DeviceStatusReport(DSRMode ps) {
|
|||||||
using SignalHandler = void(int);
|
using SignalHandler = void(int);
|
||||||
std::stack<std::function<void()>> on_exit_functions;
|
std::stack<std::function<void()>> on_exit_functions;
|
||||||
void OnExit(int signal) {
|
void OnExit(int signal) {
|
||||||
|
(void)signal;
|
||||||
while (!on_exit_functions.empty()) {
|
while (!on_exit_functions.empty()) {
|
||||||
on_exit_functions.top()();
|
on_exit_functions.top()();
|
||||||
on_exit_functions.pop();
|
on_exit_functions.pop();
|
||||||
}
|
}
|
||||||
if (signal)
|
|
||||||
std::raise(signal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto install_signal_handler = [](int sig, SignalHandler handler) {
|
auto install_signal_handler = [](int sig, SignalHandler handler) {
|
||||||
@ -279,12 +279,12 @@ CapturedMouse ScreenInteractive::CaptureMouse() {
|
|||||||
void ScreenInteractive::Loop(Component component) {
|
void ScreenInteractive::Loop(Component component) {
|
||||||
on_exit_functions.push([this] { ExitLoopClosure()(); });
|
on_exit_functions.push([this] { ExitLoopClosure()(); });
|
||||||
|
|
||||||
// Install a SIGINT handler and restore the old handler on exit.
|
// Install signal handlers to restore the terminal state on exit. The default
|
||||||
auto old_sigint_handler = std::signal(SIGINT, OnExit);
|
// signal handlers are restored on exit.
|
||||||
on_exit_functions.push(
|
for (int signal : {SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, SIGFPE})
|
||||||
[old_sigint_handler]() { std::signal(SIGINT, old_sigint_handler); });
|
install_signal_handler(signal, OnExit);
|
||||||
|
|
||||||
// Save the old terminal configuration and restore it on exit.
|
// Save the old terminal configuration and restore it on exit.
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Enable VT processing on stdout and stdin
|
// Enable VT processing on stdout and stdin
|
||||||
auto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
auto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
52
src/ftxui/component/screen_interactive_test.cpp
Normal file
52
src/ftxui/component/screen_interactive_test.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <gtest/gtest-message.h> // for Message
|
||||||
|
#include <gtest/gtest-test-part.h> // for TestPartResult
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
|
#include "ftxui/component/component.hpp"
|
||||||
|
#include "ftxui/component/screen_interactive.hpp"
|
||||||
|
#include "ftxui/dom/elements.hpp"
|
||||||
|
#include "gtest/gtest_pred_impl.h" // for AssertionResult, Test, EXPECT_EQ
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool TestSignal(int signal) {
|
||||||
|
int called = 0;
|
||||||
|
// The tree of components. This defines how to navigate using the keyboard.
|
||||||
|
auto component = Renderer([&] {
|
||||||
|
called++;
|
||||||
|
std::raise(signal);
|
||||||
|
called++;
|
||||||
|
return text(L"");
|
||||||
|
});
|
||||||
|
|
||||||
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
|
screen.Loop(component);
|
||||||
|
|
||||||
|
EXPECT_EQ(called, 2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(ScreenInteractive, Signal_SIGTERM) {
|
||||||
|
TestSignal(SIGTERM);
|
||||||
|
}
|
||||||
|
TEST(ScreenInteractive, Signal_SIGSEGV) {
|
||||||
|
TestSignal(SIGSEGV);
|
||||||
|
}
|
||||||
|
TEST(ScreenInteractive, Signal_SIGINT) {
|
||||||
|
TestSignal(SIGINT);
|
||||||
|
}
|
||||||
|
TEST(ScreenInteractive, Signal_SIGILL) {
|
||||||
|
TestSignal(SIGILL);
|
||||||
|
}
|
||||||
|
TEST(ScreenInteractive, Signal_SIGABRT) {
|
||||||
|
TestSignal(SIGABRT);
|
||||||
|
}
|
||||||
|
TEST(ScreenInteractive, Signal_SIGFPE) {
|
||||||
|
TestSignal(SIGFPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
|
// the LICENSE file.
|
Loading…
Reference in New Issue
Block a user