Added signal handler

This commit is contained in:
aristocratos 2021-06-09 19:47:49 +02:00
parent dbb5a0599b
commit 10a8bfe39e
7 changed files with 78 additions and 28 deletions

View file

@ -4,7 +4,7 @@ CPP = g++
override CPPFLAGS += -std=c++20 -pthread override CPPFLAGS += -std=c++20 -pthread
OPTFLAG = -O3 OPTFLAG = -O3
INFOFLAGS += -Wall -Wextra -Wno-stringop-overread -pedantic INFOFLAGS += -Wall -Wextra -Wno-stringop-overread -pedantic
INCLUDES = -I./src -I./include INCLUDES = -Isrc -Iinclude
btop: btop.cpp btop: btop.cpp
@mkdir -p bin @mkdir -p bin

View file

@ -21,6 +21,7 @@ tab-size = 4
#include <array> #include <array>
#include <list> #include <list>
#include <vector> #include <vector>
#include <csignal>
#include <thread> #include <thread>
#include <future> #include <future>
#include <atomic> #include <atomic>
@ -51,7 +52,7 @@ namespace Global {
#include <btop_menu.h> #include <btop_menu.h>
#if defined(__linux__) #if defined(__linux__)
#define LINUX 1 #define LINUX
#include <btop_linux.h> #include <btop_linux.h>
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__) #elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
#include <sys/param.h> #include <sys/param.h>
@ -62,7 +63,7 @@ namespace Global {
#elif defined(__APPLE__) && defined(__MACH__) #elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h> #include <TargetConditionals.h>
#if TARGET_OS_MAC == 1 #if TARGET_OS_MAC == 1
#define OSX 1 #define OSX
// #include <btop_osx.h> // #include <btop_osx.h>
#error OSX support not yet implemented! #error OSX support not yet implemented!
#endif #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 (Global::quitting) return;
if (Term::initialized) { if (Term::initialized) {
Term::restore(); 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)); if (Global::debug) Logger::debug("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time));
Global::quitting = true; 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 _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 //? Generate the btop++ banner
void banner_gen() { void banner_gen() {
size_t z = 0; size_t z = 0;
@ -178,11 +207,16 @@ int main(int argc, char **argv){
if (argc > 1) argumentParser(argc, argv); if (argc > 1) argumentParser(argc, argv);
std::atexit(_exit_handler); 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 //? Linux init
#if defined(LINUX) #if defined(LINUX)
Global::coreCount = sysconf(_SC_NPROCESSORS_ONLN); Global::coreCount = sysconf(_SC_NPROCESSORS_ONLN);
if (Global::coreCount < 1) Global::coreCount = 1; if (Global::coreCount < 1) Global::coreCount = 1;
{ {
std::error_code ec; std::error_code ec;
Global::self_path = fs::read_symlink("/proc/self/exe", ec).remove_filename(); Global::self_path = fs::read_symlink("/proc/self/exe", ec).remove_filename();
@ -261,7 +295,7 @@ int main(int argc, char **argv){
//* ------------------------------------------------ TESTING ------------------------------------------------------ //* ------------------------------------------------ TESTING ------------------------------------------------------
Global::debuginit = false; Global::debuginit = true;
// cout << Theme("main_bg") << Term::clear << flush; // cout << Theme("main_bg") << Term::clear << flush;
// bool thread_test = false; // bool thread_test = false;
@ -453,8 +487,8 @@ int main(int argc, char **argv){
greyscale.push_back(Theme::dec_to_color(xc, xc, xc)); 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}); 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 += rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 69) + " Threads: " + 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; ljust("User:", 10) + " " + rjust("MemB", 5) + " " + rjust("Cpu%", 14) + "\n" + Mv::save;
while (key != "q") { while (key != "q") {

View file

@ -40,7 +40,7 @@ namespace Config {
atomic<bool> locked (false); atomic<bool> locked (false);
atomic<bool> writelock (false); atomic<bool> writelock (false);
bool changed = false; unordered_flat_map<string, bool> changed;
unordered_flat_map<string, string> strings = { unordered_flat_map<string, string> strings = {
{"color_theme", "Default"}, {"color_theme", "Default"},
@ -104,23 +104,22 @@ namespace Config {
bool _locked(){ bool _locked(){
atomic_wait(writelock); atomic_wait(writelock);
if (!changed) changed = true;
return locked.load(); return locked.load();
} }
} }
//* Return config value <name> as a bool //* Return bool config value <name>
bool& getB(string name){ const bool& getB(string name){
return bools.at(name); return bools.at(name);
} }
//* Return config value <name> as a int //* Return integer config value <name>
int& getI(string name){ const int& getI(string name){
return ints.at(name); return ints.at(name);
} }
//* Return config value <name> as a string //* Return string config value <name>
string& getS(string name){ const string& getS(string name){
return strings.at(name); return strings.at(name);
} }
@ -128,18 +127,21 @@ namespace Config {
void set(string name, bool value){ void set(string name, bool value){
if (_locked()) boolsTmp.insert_or_assign(name, value); if (_locked()) boolsTmp.insert_or_assign(name, value);
else bools.at(name) = value; else bools.at(name) = value;
changed.insert_or_assign(name, true);
} }
//* Set config value <name> to int <value> //* Set config value <name> to int <value>
void set(string name, int value){ void set(string name, int value){
if (_locked()) intsTmp.insert_or_assign(name, value); if (_locked()) intsTmp.insert_or_assign(name, value);
ints.at(name) = value; ints.at(name) = value;
changed.insert_or_assign(name, true);
} }
//* Set config value <name> to string <value> //* Set config value <name> to string <value>
void set(string name, string value){ void set(string name, string value){
if (_locked()) stringsTmp.insert_or_assign(name, value); if (_locked()) stringsTmp.insert_or_assign(name, value);
else strings.at(name) = value; else strings.at(name) = value;
changed.insert_or_assign(name, true);
} }
//* Flip config bool <name> //* Flip config bool <name>
@ -149,6 +151,7 @@ namespace Config {
else boolsTmp.insert_or_assign(name, (!bools.at(name))); else boolsTmp.insert_or_assign(name, (!bools.at(name)));
} }
else bools.at(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 //* Wait if locked then lock config and cache changes until unlock
@ -184,6 +187,19 @@ namespace Config {
void load(){ void load(){
if (conf_file.empty()) return; 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 #endif

View file

@ -91,21 +91,21 @@ namespace Draw {
//* Draw horizontal lines //* Draw horizontal lines
for (uint hpos : {c.y, c.y + c.height - 1}){ 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 //* Draw vertical lines and fill if enabled
for (uint hpos : iota(c.y + 1, c.y + c.height - 1)){ for (uint hpos : iota(c.y + 1, c.y + c.height - 1)){
out += Mv::to(hpos, c.x) + Symbols::v_line + 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; Symbols::v_line;
} }
//* Draw corners //* Draw corners
out += Mv::to(c.y, c.x) + Symbols::left_up + 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) + 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 //* Draw titles if defined
if (!c.title.empty()){ if (!c.title.empty()){
@ -117,7 +117,7 @@ namespace Draw {
Fx::ub + lcolor + Symbols::title_right; 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 //* Class holding a percentage meter

View file

@ -155,8 +155,8 @@ namespace Proc {
return current_procs; return current_procs;
} }
string pid_str = d.path().filename();
bool new_cache = false; bool new_cache = false;
string pid_str = d.path().filename();
if (d.is_directory() && isdigit(pid_str[0])) { if (d.is_directory() && isdigit(pid_str[0])) {
npids++; npids++;
proc_info new_proc (stoul(pid_str)); 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 //* 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; double max = 10.0, target = 30.0;
for (size_t i = 0, offset = 0; i < procs.size(); i++) { for (size_t i = 0, offset = 0; i < procs.size(); i++) {
if (i <= 5 && procs[i].cpu_p > max) max = procs[i].cpu_p; if (i <= 5 && procs[i].cpu_p > max) max = procs[i].cpu_p;

View file

@ -257,7 +257,7 @@ namespace Theme {
//? If only _start was defined fill array with _start color //? If only _start was defined fill array with _start color
c_gradient.fill(colors[name]); c_gradient.fill(colors[name]);
} }
gradients[wname] = c_gradient; gradients[wname].swap(c_gradient);
} }
} }
} }

View file

@ -267,8 +267,8 @@ namespace Tools {
return (str == "true") || (str == "false") || (str == "True") || (str == "False"); return (str == "true") || (str == "false") || (str == "True") || (str == "False");
} }
//* Check if a string is a valid integer value //* Check if a string is a valid positive integer value
bool isint(string& str){ bool isuint(string& str){
return all_of(str.begin(), str.end(), ::isdigit); return all_of(str.begin(), str.end(), ::isdigit);
} }
@ -428,13 +428,13 @@ namespace Tools {
} }
#if __GNUC__ > 10 #if (__GNUC__ > 10)
//* Redirects to atomic wait //* Redirects to atomic wait
void atomic_wait(atomic<bool>& atom, bool val=true){ void atomic_wait(atomic<bool>& atom, bool val=true){
atom.wait(val); atom.wait(val);
} }
#else #else
//* Crude implementation of atomic wait for GCC < 11 //* Crude implementation of atomic wait for GCC 10
void atomic_wait(atomic<bool>& atom, bool val=true){ void atomic_wait(atomic<bool>& atom, bool val=true){
while (atom.load() == val) sleep_ms(1); while (atom.load() == val) sleep_ms(1);
} }