From 1c478f38601d6b355d8b2d7210e51cd678c91ea3 Mon Sep 17 00:00:00 2001 From: ttibsi Date: Wed, 19 Feb 2025 21:00:25 +0000 Subject: [PATCH 1/2] cleanup signals --- rawterm/core.cpp | 23 ++++++++++------------- rawterm/core.h | 7 +++---- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/rawterm/core.cpp b/rawterm/core.cpp index 4cdacc4..e693dcd 100644 --- a/rawterm/core.cpp +++ b/rawterm/core.cpp @@ -8,6 +8,7 @@ namespace rawterm { namespace detail { + [[nodiscard]] bool is_debug() { auto raw_env_var = std::getenv("RAWTERM_DEBUG"); if (raw_env_var == nullptr) { @@ -19,6 +20,7 @@ namespace rawterm { } } // namespace detail + rawterm::Mod Key::getMod() { if (mod.empty()) { return rawterm::Mod::None; @@ -103,18 +105,10 @@ namespace rawterm { is_signals_enabled = true; #endif } - - void sigtstp_handler(std::function func) { - if (detail::sigtstp_called) { - func(); - detail::sigtstp_called = false; - } - } - - void sigcont_handler(std::function func) { - if (detail::sigcont_called) { + void signal_handler(Signal sig, std::function func) { + if (detail::sig_sent == sig) { func(); - detail::sigcont_called = false; + detail::sig_sent = Signal::NONE; } } @@ -122,17 +116,20 @@ namespace rawterm { #if __linux__ // Backgrounding std::signal(SIGTSTP, [](int) { - detail::sigtstp_called = true; + detail::sig_sent = Signal::SIG_TSTP; rawterm::exit_alt_screen(); std::raise(SIGSTOP); }); // Foregrounding std::signal(SIGCONT, [](int) { - detail::sigcont_called = true; + detail::sig_sent = Signal::SIG_CONT; rawterm::enter_alt_screen(); rawterm::enable_raw_mode(); }); + + // Window resizing + std::signal(SIGWINCH, [](int) { detail::sig_sent = Signal::SIG_WINCH; }); #endif std::string characters = std::string(32, '\0'); diff --git a/rawterm/core.h b/rawterm/core.h index aa75631..1e1d227 100644 --- a/rawterm/core.h +++ b/rawterm/core.h @@ -32,13 +32,13 @@ #include "screen.h" namespace rawterm { + enum class Signal { SIG_TSTP, SIG_CONT, SIG_WINCH, NONE }; namespace detail { #if __linux__ inline termios orig; #endif - inline bool sigtstp_called = false; - inline bool sigcont_called = false; + inline Signal sig_sent = Signal::NONE; // Used for polling in process_keypress() inline pollfd fd {STDIN_FILENO, POLLIN, POLLOUT}; @@ -106,8 +106,7 @@ namespace rawterm { void enter_alt_screen(); void exit_alt_screen(); void enable_signals(); - void sigtstp_handler(std::function); - void sigcont_handler(std::function); + void signal_handler(Signal, std::function); [[nodiscard]] const std::optional process_keypress(); const rawterm::Key wait_for_input(); [[nodiscard]] const rawterm::Pos get_term_size(); From 130826d7d78355eb2d21fcd26401568471e32282 Mon Sep 17 00:00:00 2001 From: ttibsi Date: Sun, 2 Mar 2025 14:11:38 +0000 Subject: [PATCH 2/2] multithread signals --- examples/borders.cpp | 3 ++- examples/keys.cpp | 5 +++- rawterm/core.cpp | 55 ++++++++++++++++++++++++++------------------ rawterm/core.h | 3 ++- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/examples/borders.cpp b/examples/borders.cpp index 0fd88b7..523ea47 100644 --- a/examples/borders.cpp +++ b/examples/borders.cpp @@ -10,7 +10,7 @@ int main() { rawterm::enable_raw_mode(); rawterm::enter_alt_screen(); - rawterm::enable_signals(); + auto signals_thread = rawterm::enable_signals(); rawterm::Cursor::cursor_hide(); rawterm::Cursor cur; @@ -29,5 +29,6 @@ int main() { std::ignore = rawterm::wait_for_input(); rawterm::Cursor::cursor_show(); + signals_thread.join(); return 0; } diff --git a/examples/keys.cpp b/examples/keys.cpp index 042f676..e2304aa 100644 --- a/examples/keys.cpp +++ b/examples/keys.cpp @@ -11,7 +11,7 @@ int main() { rawterm::enable_raw_mode(); rawterm::enter_alt_screen(); - rawterm::enable_signals(); + auto signals_thread = rawterm::enable_signals(); rawterm::clear_screen(); @@ -42,5 +42,8 @@ int main() { // Optional explicit call to exit_alt_screen to return to standard screen. // This will happen even without calling this function explicitly rawterm::exit_alt_screen(); + + // Don't forget to join back to the main thread + signals_thread.join(); return 0; } diff --git a/rawterm/core.cpp b/rawterm/core.cpp index e693dcd..f1a34b1 100644 --- a/rawterm/core.cpp +++ b/rawterm/core.cpp @@ -1,7 +1,10 @@ #include "core.h" #include +#include #include +#include +#include #include "cursor.h" #include "exceptions.h" @@ -99,12 +102,34 @@ namespace rawterm { std::cout << "\x1B[?1049l" << std::flush; } - bool is_signals_enabled = false; - void enable_signals() { + inline bool is_signals_enabled = false; + [[nodiscard]] std::thread enable_signals() { #if __linux__ is_signals_enabled = true; + + std::thread thr([] { + // Backgrounding + std::signal(SIGTSTP, [](int) { + detail::sig_sent = Signal::SIG_TSTP; + rawterm::exit_alt_screen(); + std::raise(SIGSTOP); + }); + + // Foregrounding + std::signal(SIGCONT, [](int) { + detail::sig_sent = Signal::SIG_CONT; + rawterm::enter_alt_screen(); + rawterm::enable_raw_mode(); + }); + + // Window resizing + std::signal(SIGWINCH, [](int) { detail::sig_sent = Signal::SIG_WINCH; }); + }); + + return thr; #endif } + void signal_handler(Signal sig, std::function func) { if (detail::sig_sent == sig) { func(); @@ -113,25 +138,6 @@ namespace rawterm { } [[nodiscard]] const std::optional process_keypress() { -#if __linux__ - // Backgrounding - std::signal(SIGTSTP, [](int) { - detail::sig_sent = Signal::SIG_TSTP; - rawterm::exit_alt_screen(); - std::raise(SIGSTOP); - }); - - // Foregrounding - std::signal(SIGCONT, [](int) { - detail::sig_sent = Signal::SIG_CONT; - rawterm::enter_alt_screen(); - rawterm::enable_raw_mode(); - }); - - // Window resizing - std::signal(SIGWINCH, [](int) { detail::sig_sent = Signal::SIG_WINCH; }); -#endif - std::string characters = std::string(32, '\0'); int pollResult = poll(&detail::fd, 1, 0); @@ -145,9 +151,14 @@ namespace rawterm { } else if (pollResult == 0) { return {}; + // interrupted system call -- SIGWINCH interrupting poll() + } else if (errno == 4) { + return {}; + // Error } else { - throw rawterm::KeypressError("An unknown error occured"); + throw rawterm::KeypressError( + std::format("A poll error occured: {} - {}", errno, std::strerror(errno))); } std::stringstream ss; diff --git a/rawterm/core.h b/rawterm/core.h index 1e1d227..be49a03 100644 --- a/rawterm/core.h +++ b/rawterm/core.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -105,7 +106,7 @@ namespace rawterm { [[maybe_unused]] int enable_raw_mode(); void enter_alt_screen(); void exit_alt_screen(); - void enable_signals(); + [[nodiscard]] std::thread enable_signals(); void signal_handler(Signal, std::function); [[nodiscard]] const std::optional process_keypress(); const rawterm::Key wait_for_input();