Merge branch 'main' into config-read-only

This commit is contained in:
Jakob P. Liljenberg 2024-01-03 17:05:24 +01:00 committed by GitHub
commit 6637485f0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 97 deletions

View file

@ -176,7 +176,7 @@ void term_resize(bool force) {
static atomic<bool> resizing (false); static atomic<bool> resizing (false);
if (Input::polling) { if (Input::polling) {
Global::resized = true; Global::resized = true;
Input::interrupt = true; Input::interrupt();
return; return;
} }
atomic_lock lck(resizing, true); atomic_lock lck(resizing, true);
@ -246,7 +246,7 @@ void term_resize(bool force) {
else if (not Term::refresh()) break; else if (not Term::refresh()) break;
} }
Input::interrupt = true; Input::interrupt();
} }
//* Exit handler; stops threads, restores terminal and saves config changes //* Exit handler; stops threads, restores terminal and saves config changes
@ -321,7 +321,7 @@ void _signal_handler(const int sig) {
if (Runner::active) { if (Runner::active) {
Global::should_quit = true; Global::should_quit = true;
Runner::stopping = true; Runner::stopping = true;
Input::interrupt = true; Input::interrupt();
} }
else { else {
clean_quit(0); clean_quit(0);
@ -331,7 +331,7 @@ void _signal_handler(const int sig) {
if (Runner::active) { if (Runner::active) {
Global::should_sleep = true; Global::should_sleep = true;
Runner::stopping = true; Runner::stopping = true;
Input::interrupt = true; Input::interrupt();
} }
else { else {
_sleep(); _sleep();
@ -343,6 +343,9 @@ void _signal_handler(const int sig) {
case SIGWINCH: case SIGWINCH:
term_resize(); term_resize();
break; break;
case SIGUSR1:
// Input::poll interrupt
break;
} }
} }
@ -477,7 +480,7 @@ namespace Runner {
if (pt_lck.status != 0) { if (pt_lck.status != 0) {
Global::exit_error_msg = "Exception in runner thread -> pthread_mutex_lock error id: " + to_string(pt_lck.status); Global::exit_error_msg = "Exception in runner thread -> pthread_mutex_lock error id: " + to_string(pt_lck.status);
Global::thread_exception = true; Global::thread_exception = true;
Input::interrupt = true; Input::interrupt();
stopping = true; stopping = true;
} }
@ -488,7 +491,7 @@ namespace Runner {
if (active) { if (active) {
Global::exit_error_msg = "Runner thread failed to get active lock!"; Global::exit_error_msg = "Runner thread failed to get active lock!";
Global::thread_exception = true; Global::thread_exception = true;
Input::interrupt = true; Input::interrupt();
stopping = true; stopping = true;
} }
if (stopping or Global::resized) { if (stopping or Global::resized) {
@ -558,7 +561,7 @@ namespace Runner {
coreNum_reset = false; coreNum_reset = false;
Cpu::core_mapping = Cpu::get_core_mapping(); Cpu::core_mapping = Cpu::get_core_mapping();
Global::resized = true; Global::resized = true;
Input::interrupt = true; Input::interrupt();
continue; continue;
} }
@ -655,7 +658,7 @@ namespace Runner {
catch (const std::exception& e) { catch (const std::exception& e) {
Global::exit_error_msg = "Exception in runner thread -> " + string{e.what()}; Global::exit_error_msg = "Exception in runner thread -> " + string{e.what()};
Global::thread_exception = true; Global::thread_exception = true;
Input::interrupt = true; Input::interrupt();
stopping = true; stopping = true;
} }
@ -1008,6 +1011,12 @@ int main(int argc, char **argv) {
std::signal(SIGTSTP, _signal_handler); std::signal(SIGTSTP, _signal_handler);
std::signal(SIGCONT, _signal_handler); std::signal(SIGCONT, _signal_handler);
std::signal(SIGWINCH, _signal_handler); std::signal(SIGWINCH, _signal_handler);
std::signal(SIGUSR1, _signal_handler);
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &mask, &Input::signal_mask);
//? Start runner thread //? Start runner thread
Runner::thread_sem_init(); Runner::thread_sem_init();
@ -1029,9 +1038,10 @@ int main(int argc, char **argv) {
{ {
const auto [x, y] = Term::get_min_size(Config::getS("shown_boxes")); const auto [x, y] = Term::get_min_size(Config::getS("shown_boxes"));
if (Term::height < y or Term::width < x) { if (Term::height < y or Term::width < x) {
pthread_sigmask(SIG_SETMASK, &Input::signal_mask, &mask);
term_resize(true); term_resize(true);
pthread_sigmask(SIG_SETMASK, &mask, nullptr);
Global::resized = false; Global::resized = false;
Input::interrupt = false;
} }
} }

View file

@ -16,12 +16,13 @@ indent = tab
tab-size = 4 tab-size = 4
*/ */
#include <iostream> #include <limits>
#include <ranges> #include <ranges>
#include <vector> #include <vector>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <signal.h> #include <signal.h>
#include <sys/select.h>
#include <utility> #include <utility>
#include "btop_input.hpp" #include "btop_input.hpp"
@ -31,17 +32,6 @@ tab-size = 4
#include "btop_menu.hpp" #include "btop_menu.hpp"
#include "btop_draw.hpp" #include "btop_draw.hpp"
#include "btop_input.hpp"
#include "btop_tools.hpp"
#include "btop_config.hpp"
#include "btop_shared.hpp"
#include "btop_menu.hpp"
#include "btop_draw.hpp"
using std::cin;
using namespace Tools; using namespace Tools;
using namespace std::literals; // for operator""s using namespace std::literals; // for operator""s
namespace rng = std::ranges; namespace rng = std::ranges;
@ -89,83 +79,45 @@ namespace Input {
{"[24~", "f12"} {"[24~", "f12"}
}; };
std::atomic<bool> interrupt (false); sigset_t signal_mask;
std::atomic<bool> polling (false); std::atomic<bool> polling (false);
array<int, 2> mouse_pos; array<int, 2> mouse_pos;
std::unordered_map<string, Mouse_loc> mouse_mappings; std::unordered_map<string, Mouse_loc> mouse_mappings;
deque<string> history(50, ""); deque<string> history(50, "");
string old_filter; string old_filter;
string input;
struct InputThr { bool poll(const uint64_t timeout) {
InputThr() : thr(run, this) {
}
static void run(InputThr* that) {
that->runImpl();
}
void runImpl() {
char ch = 0;
// TODO(pg83): read whole buffer
while (cin.get(ch)) {
std::lock_guard<std::mutex> g(lock);
current.push_back(ch);
if (current.size() > 100) {
current.clear();
}
}
}
size_t avail() {
std::lock_guard<std::mutex> g(lock);
return current.size();
}
std::string get() {
std::string res;
{
std::lock_guard<std::mutex> g(lock);
res.swap(current);
}
return res;
}
static InputThr& instance() {
// intentional memory leak, to simplify shutdown process
static InputThr* input = new InputThr();
return *input;
}
std::string current;
// TODO(pg83): use std::conditional_variable instead of sleep
std::mutex lock;
std::thread thr;
};
bool poll(int timeout) {
atomic_lock lck(polling); atomic_lock lck(polling);
if (timeout < 1) return InputThr::instance().avail() > 0; fd_set fds;
while (timeout > 0) { FD_ZERO(&fds);
if (interrupt) { FD_SET(STDIN_FILENO, &fds);
interrupt = false; struct timespec wait;
return false; struct timespec *waitptr = nullptr;
}
if (InputThr::instance().avail() > 0) return true; if(timeout != std::numeric_limits<uint64_t>::max()) {
sleep_ms(timeout < 10 ? timeout : 10); wait.tv_sec = timeout / 1000;
timeout -= 10; wait.tv_nsec = (timeout % 1000) * 1000000;
waitptr = &wait;
} }
if(pselect(STDIN_FILENO + 1, &fds, nullptr, nullptr, waitptr, &signal_mask) > 0) {
input.clear();
char buf[1024];
ssize_t count = 0;
while((count = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
input.append(std::string_view(buf, count));
}
return true;
}
return false; return false;
} }
string get() { string get() {
string key = InputThr::instance().get(); string key = input;
if (not key.empty()) { if (not key.empty()) {
//? Remove escape code prefix if present //? Remove escape code prefix if present
if (key.substr(0, 2) == Fx::e) { if (key.substr(0, 2) == Fx::e) {
@ -238,12 +190,14 @@ namespace Input {
} }
string wait() { string wait() {
while (InputThr::instance().avail() < 1) { while(not poll(std::numeric_limits<uint64_t>::max())) {}
sleep_ms(10);
}
return get(); return get();
} }
void interrupt() {
kill(getpid(), SIGUSR1);
}
void clear() { void clear() {
// do not need it, actually // do not need it, actually
} }

View file

@ -29,9 +29,9 @@ using std::atomic;
using std::deque; using std::deque;
using std::string; using std::string;
/* The input functions relies on the following std::cin options being set: /* The input functions rely on the following termios parameters being set:
cin.sync_with_stdio(false); Non-canonical mode (c_lflags & ~(ICANON))
cin.tie(nullptr); VMIN and VTIME (c_cc) set to 0
These will automatically be set when running Term::init() from btop_tools.cpp These will automatically be set when running Term::init() from btop_tools.cpp
*/ */
@ -45,7 +45,9 @@ namespace Input {
//? line, col, height, width //? line, col, height, width
extern std::unordered_map<string, Mouse_loc> mouse_mappings; extern std::unordered_map<string, Mouse_loc> mouse_mappings;
extern atomic<bool> interrupt; //* Signal mask used during polling read
extern sigset_t signal_mask;
extern atomic<bool> polling; extern atomic<bool> polling;
//* Mouse column and line position //* Mouse column and line position
@ -55,7 +57,7 @@ namespace Input {
extern deque<string> history; extern deque<string> history;
//* Poll keyboard & mouse input for <timeout> ms and return input availabilty as a bool //* Poll keyboard & mouse input for <timeout> ms and return input availabilty as a bool
bool poll(int timeout=0); bool poll(const uint64_t timeout=0);
//* Get a key or mouse action from input //* Get a key or mouse action from input
string get(); string get();
@ -63,6 +65,9 @@ namespace Input {
//* Wait until input is available and return key //* Wait until input is available and return key
string wait(); string wait();
//* Interrupt poll/wait
void interrupt();
//* Clears last entered key //* Clears last entered key
void clear(); void clear();

View file

@ -37,7 +37,6 @@ tab-size = 4
#include "btop_tools.hpp" #include "btop_tools.hpp"
#include "btop_config.hpp" #include "btop_config.hpp"
using std::cin;
using std::cout; using std::cout;
using std::floor; using std::floor;
using std::flush; using std::flush;
@ -77,7 +76,11 @@ namespace Term {
struct termios settings; struct termios settings;
if (tcgetattr(STDIN_FILENO, &settings)) return false; if (tcgetattr(STDIN_FILENO, &settings)) return false;
if (on) settings.c_lflag |= ICANON; if (on) settings.c_lflag |= ICANON;
else settings.c_lflag &= ~(ICANON); else {
settings.c_lflag &= ~(ICANON);
settings.c_cc[VMIN] = 0;
settings.c_cc[VTIME] = 0;
}
if (tcsetattr(STDIN_FILENO, TCSANOW, &settings)) return false; if (tcsetattr(STDIN_FILENO, TCSANOW, &settings)) return false;
if (on) setlinebuf(stdin); if (on) setlinebuf(stdin);
else setbuf(stdin, nullptr); else setbuf(stdin, nullptr);
@ -152,12 +155,10 @@ namespace Term {
//? Disable stream sync - this does not seem to work on OpenBSD //? Disable stream sync - this does not seem to work on OpenBSD
#ifndef __OpenBSD__ #ifndef __OpenBSD__
cin.sync_with_stdio(false);
cout.sync_with_stdio(false); cout.sync_with_stdio(false);
#endif #endif
//? Disable stream ties //? Disable stream ties
cin.tie(nullptr);
cout.tie(nullptr); cout.tie(nullptr);
echo(false); echo(false);
linebuffered(false); linebuffered(false);