From 10a8bfe39e2f9dcb9849ca1ee35e9a1a8b8871bf Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 9 Jun 2021 19:47:49 +0200 Subject: [PATCH] Added signal handler --- Makefile | 2 +- btop.cpp | 48 ++++++++++++++++++++++++++++++++++++++++------- src/btop_config.h | 32 +++++++++++++++++++++++-------- src/btop_draw.h | 10 +++++----- src/btop_linux.h | 4 ++-- src/btop_theme.h | 2 +- src/btop_tools.h | 8 ++++---- 7 files changed, 78 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 39db6a2..19265ad 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CPP = g++ override CPPFLAGS += -std=c++20 -pthread OPTFLAG = -O3 INFOFLAGS += -Wall -Wextra -Wno-stringop-overread -pedantic -INCLUDES = -I./src -I./include +INCLUDES = -Isrc -Iinclude btop: btop.cpp @mkdir -p bin diff --git a/btop.cpp b/btop.cpp index 2430645..416b73d 100644 --- a/btop.cpp +++ b/btop.cpp @@ -21,6 +21,7 @@ tab-size = 4 #include #include #include +#include #include #include #include @@ -51,7 +52,7 @@ namespace Global { #include #if defined(__linux__) - #define LINUX 1 + #define LINUX #include #elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__) #include @@ -62,7 +63,7 @@ namespace Global { #elif defined(__APPLE__) && defined(__MACH__) #include #if TARGET_OS_MAC == 1 - #define OSX 1 + #define OSX // #include #error OSX support not yet implemented! #endif @@ -113,7 +114,7 @@ void argumentParser(int argc, char **argv){ } } -void clean_quit(int signal){ +void clean_quit(int sig){ if (Global::quitting) return; if (Term::initialized) { Term::restore(); @@ -121,11 +122,39 @@ void clean_quit(int signal){ } if (Global::debug) Logger::debug("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time)); Global::quitting = true; - if (signal != -1) exit(signal); + Config::write(); + if (sig != -1) exit(sig); +} + +void sleep_now(){ + if (Term::initialized) { + Term::restore(); + if (!Global::debuginit) cout << Term::normal_screen << Term::show_cursor << flush; + } + std::raise(SIGSTOP); +} + +void resume_now(){ + Term::init(); + if (!Global::debuginit) cout << Term::alt_screen << Term::hide_cursor << flush; } void _exit_handler() { clean_quit(-1); } +void _signal_handler(int sig) { + switch (sig) { + case SIGINT: + clean_quit(0); + break; + case SIGTSTP: + sleep_now(); + break; + case SIGCONT: + resume_now(); + break; + } +} + //? Generate the btop++ banner void banner_gen() { size_t z = 0; @@ -178,11 +207,16 @@ int main(int argc, char **argv){ if (argc > 1) argumentParser(argc, argv); std::atexit(_exit_handler); + std::at_quick_exit(_exit_handler); + std::signal(SIGINT, _signal_handler); + std::signal(SIGTSTP, _signal_handler); + std::signal(SIGCONT, _signal_handler); //? Linux init #if defined(LINUX) Global::coreCount = sysconf(_SC_NPROCESSORS_ONLN); if (Global::coreCount < 1) Global::coreCount = 1; + { std::error_code ec; Global::self_path = fs::read_symlink("/proc/self/exe", ec).remove_filename(); @@ -261,7 +295,7 @@ int main(int argc, char **argv){ //* ------------------------------------------------ TESTING ------------------------------------------------------ - Global::debuginit = false; + Global::debuginit = true; // cout << Theme("main_bg") << Term::clear << flush; // bool thread_test = false; @@ -453,8 +487,8 @@ int main(int argc, char **argv){ greyscale.push_back(Theme::dec_to_color(xc, xc, xc)); } - string pbox = Draw::createBox({.x = 0, .y = 10, .width = Term::width, .height = Term::height - 16, .line_color = Theme::c("proc_box"), .title = "testbox", .title2 = "below", .fill = false, .num = 7}); - pbox += rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 69) + " Threads: " + + string pbox = Draw::createBox({.x = 1, .y = 10, .width = Term::width, .height = Term::height - 16, .line_color = Theme::c("proc_box"), .title = "testbox", .title2 = "below", .fill = false, .num = 7}); + pbox += Mv::r(1) + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 70) + " Threads: " + ljust("User:", 10) + " " + rjust("MemB", 5) + " " + rjust("Cpu%", 14) + "\n" + Mv::save; while (key != "q") { diff --git a/src/btop_config.h b/src/btop_config.h index 54c6eeb..a8671a8 100644 --- a/src/btop_config.h +++ b/src/btop_config.h @@ -40,7 +40,7 @@ namespace Config { atomic locked (false); atomic writelock (false); - bool changed = false; + unordered_flat_map changed; unordered_flat_map strings = { {"color_theme", "Default"}, @@ -104,23 +104,22 @@ namespace Config { bool _locked(){ atomic_wait(writelock); - if (!changed) changed = true; return locked.load(); } } - //* Return config value as a bool - bool& getB(string name){ + //* Return bool config value + const bool& getB(string name){ return bools.at(name); } - //* Return config value as a int - int& getI(string name){ + //* Return integer config value + const int& getI(string name){ return ints.at(name); } - //* Return config value as a string - string& getS(string name){ + //* Return string config value + const string& getS(string name){ return strings.at(name); } @@ -128,18 +127,21 @@ namespace Config { void set(string name, bool value){ if (_locked()) boolsTmp.insert_or_assign(name, value); else bools.at(name) = value; + changed.insert_or_assign(name, true); } //* Set config value to int void set(string name, int value){ if (_locked()) intsTmp.insert_or_assign(name, value); ints.at(name) = value; + changed.insert_or_assign(name, true); } //* Set config value to string void set(string name, string value){ if (_locked()) stringsTmp.insert_or_assign(name, value); else strings.at(name) = value; + changed.insert_or_assign(name, true); } //* Flip config bool @@ -149,6 +151,7 @@ namespace Config { else boolsTmp.insert_or_assign(name, (!bools.at(name))); } else bools.at(name) = !bools.at(name); + changed.insert_or_assign(name, true); } //* Wait if locked then lock config and cache changes until unlock @@ -184,6 +187,19 @@ namespace Config { void load(){ if (conf_file.empty()) return; } + + void write(){ + if (conf_file.empty() || changed.empty()) return; + + if (Logger::loglevel > 3) { + string items; + for (auto item : Config::changed) { + items += item.first + ", "; + } + items.pop_back(); items.pop_back(); + Logger::debug("Writing out new config values for: " + items); + } + } } #endif \ No newline at end of file diff --git a/src/btop_draw.h b/src/btop_draw.h index 029779b..862e8b2 100644 --- a/src/btop_draw.h +++ b/src/btop_draw.h @@ -91,21 +91,21 @@ namespace Draw { //* Draw horizontal lines for (uint hpos : {c.y, c.y + c.height - 1}){ - out += Mv::to(hpos, c.x) + Symbols::h_line * (c.width); + out += Mv::to(hpos, c.x) + Symbols::h_line * (c.width - 1); } //* Draw vertical lines and fill if enabled for (uint hpos : iota(c.y + 1, c.y + c.height - 1)){ out += Mv::to(hpos, c.x) + Symbols::v_line + - ((c.fill) ? string(c.width - 1, ' ') : Mv::r(c.width - 1)) + + ((c.fill) ? string(c.width - 2, ' ') : Mv::r(c.width - 2)) + Symbols::v_line; } //* Draw corners out += Mv::to(c.y, c.x) + Symbols::left_up + - Mv::to(c.y, c.x + c.width) + Symbols::right_up + + Mv::to(c.y, c.x + c.width - 1) + Symbols::right_up + Mv::to(c.y + c.height - 1, c.x) + Symbols::left_down + - Mv::to(c.y + c.height - 1, c.x + c.width) + Symbols::right_down; + Mv::to(c.y + c.height - 1, c.x + c.width - 1) + Symbols::right_down; //* Draw titles if defined if (!c.title.empty()){ @@ -117,7 +117,7 @@ namespace Draw { Fx::ub + lcolor + Symbols::title_right; } - return out + Fx::reset + Mv::to(c.y + 1, c.x + 2); + return out + Fx::reset + Mv::to(c.y + 1, c.x + 1); } //* Class holding a percentage meter diff --git a/src/btop_linux.h b/src/btop_linux.h index cbd3f1f..235d54d 100644 --- a/src/btop_linux.h +++ b/src/btop_linux.h @@ -155,8 +155,8 @@ namespace Proc { return current_procs; } - string pid_str = d.path().filename(); bool new_cache = false; + string pid_str = d.path().filename(); if (d.is_directory() && isdigit(pid_str[0])) { npids++; proc_info new_proc (stoul(pid_str)); @@ -314,7 +314,7 @@ namespace Proc { ); //* When using "cpu lazy" sorting push processes with high cpu usage to the front regardless of cumulative usage - if (sort_map.at(sorting) == 7 && !reverse) { + if (sorting == "cpu lazy" && !reverse) { double max = 10.0, target = 30.0; for (size_t i = 0, offset = 0; i < procs.size(); i++) { if (i <= 5 && procs[i].cpu_p > max) max = procs[i].cpu_p; diff --git a/src/btop_theme.h b/src/btop_theme.h index 900087a..637326d 100644 --- a/src/btop_theme.h +++ b/src/btop_theme.h @@ -257,7 +257,7 @@ namespace Theme { //? If only _start was defined fill array with _start color c_gradient.fill(colors[name]); } - gradients[wname] = c_gradient; + gradients[wname].swap(c_gradient); } } } diff --git a/src/btop_tools.h b/src/btop_tools.h index f937b0c..9d61790 100644 --- a/src/btop_tools.h +++ b/src/btop_tools.h @@ -267,8 +267,8 @@ namespace Tools { return (str == "true") || (str == "false") || (str == "True") || (str == "False"); } - //* Check if a string is a valid integer value - bool isint(string& str){ + //* Check if a string is a valid positive integer value + bool isuint(string& str){ return all_of(str.begin(), str.end(), ::isdigit); } @@ -428,13 +428,13 @@ namespace Tools { } - #if __GNUC__ > 10 + #if (__GNUC__ > 10) //* Redirects to atomic wait void atomic_wait(atomic& atom, bool val=true){ atom.wait(val); } #else - //* Crude implementation of atomic wait for GCC < 11 + //* Crude implementation of atomic wait for GCC 10 void atomic_wait(atomic& atom, bool val=true){ while (atom.load() == val) sleep_ms(1); }