From 086e49838804517834bb2d027f6c7eccfe87813c Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Sat, 3 Dec 2016 15:46:48 +0100 Subject: [PATCH] fix: Replace process on reload --- include/components/controller.hpp | 4 +- include/utils/process.hpp | 1 + src/components/controller.cpp | 8 +- src/main.cpp | 221 +++++++++++++++--------------- src/utils/process.cpp | 13 +- 5 files changed, 125 insertions(+), 122 deletions(-) diff --git a/include/components/controller.hpp b/include/components/controller.hpp index f4ac032b..f55a9b93 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -37,9 +37,7 @@ class controller { ~controller(); void bootstrap(bool writeback = false, bool dump_wmname = false); - - void run(); - bool completed(); + bool run(); protected: void install_sigmask(); diff --git a/include/utils/process.hpp b/include/utils/process.hpp index b4e6b613..c0d6e4e7 100644 --- a/include/utils/process.hpp +++ b/include/utils/process.hpp @@ -8,6 +8,7 @@ namespace process_util { bool in_parent_process(pid_t pid); bool in_forked_process(pid_t pid); + void exec(char* cmd, char** args); void exec(const string& cmd); pid_t wait_for_completion(pid_t process_id, int* status_addr, int waitflags = 0); diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 14ba6e62..bc17b711 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -118,6 +118,7 @@ controller::~controller() { } m_connection.flush(); + m_connection.disconnect(); } /** @@ -178,7 +179,7 @@ void controller::bootstrap(bool writeback, bool dump_wmname) { /** * Launch the controller */ -void controller::run() { +bool controller::run() { assert(!m_connection.connection_has_error()); m_log.info("Starting application"); @@ -235,12 +236,7 @@ void controller::run() { m_log.trace("controller: Removing config watch"); m_confwatch->remove(true); } -} -/** - * Get completion state - */ -bool controller::completed() { return !m_running && !m_reload; } diff --git a/src/main.cpp b/src/main.cpp index 3b679730..b0a441aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include "config.hpp" #include "utils/env.hpp" #include "utils/inotify.hpp" +#include "utils/process.hpp" #include "x11/ewmh.hpp" #include "x11/xutils.hpp" @@ -20,7 +21,8 @@ struct exit_failure {}; int main(int argc, char** argv) { uint8_t exit_code{EXIT_SUCCESS}; - stateflag quit{false}; + bool reload{false}; + int xfd; // clang-format off const command_line::options opts{ @@ -38,119 +40,120 @@ int main(int argc, char** argv) { logger& logger{configure_logger(loglevel::WARNING).create()}; - //================================================== - // Connect to X server - //================================================== - XInitThreads(); + try { + //================================================== + // Connect to X server + //================================================== + XInitThreads(); - xcb_connection_t* connection{nullptr}; + xcb_connection_t* connection{nullptr}; - if ((connection = xutils::get_connection()) == nullptr) { - logger.err("A connection to X could not be established... "); - throw exit_failure{}; - } - - int xfd{xcb_get_file_descriptor(connection)}; - - while (!quit) { - try { - //================================================== - // Parse command line arguments - //================================================== - vector args(argv + 1, argv + argc); - cliparser cli{configure_cliparser(argv[0], opts).create()}; - cli.process_input(args); - - if (cli.has("quiet")) { - logger.verbosity(loglevel::ERROR); - } else if (cli.has("log")) { - logger.verbosity(cli.get("log")); - } - - if (cli.has("help")) { - cli.usage(); - throw exit_success{}; - } else if (cli.has("version")) { - print_build_info(version_details(args)); - throw exit_success{}; - } else if (args.empty() || args[0][0] == '-') { - cli.usage(); - throw exit_failure{}; - } - - //================================================== - // Load user configuration - //================================================== - config& conf{configure_config().create()}; - - if (cli.has("config")) { - conf.load(cli.get("config"), args[0]); - } else if (env_util::has("XDG_CONFIG_HOME")) { - conf.load(env_util::get("XDG_CONFIG_HOME") + "/polybar/config", args[0]); - } else if (env_util::has("HOME")) { - conf.load(env_util::get("HOME") + "/.config/polybar/config", args[0]); - } else { - throw application_error("Define configuration using --config=PATH"); - } - - //================================================== - // Dump requested data - //================================================== - if (cli.has("dump")) { - std::cout << conf.get(conf.bar_section(), cli.get("dump")) << std::endl; - throw exit_success{}; - } - - //================================================== - // Create config watch if we should track changes - //================================================== - inotify_util::watch_t watch; - - if (cli.has("reload")) { - watch = inotify_util::make_watch(conf.filepath()); - } - - //================================================== - // Create controller - //================================================== - auto ctrl = configure_controller(watch).create>(); - - ctrl->bootstrap(cli.has("stdout"), cli.has("print-wmname")); - - if (cli.has("print-wmname")) { - throw exit_success{}; - } - - //================================================== - // Run application - //================================================== - ctrl->run(); - - if (ctrl->completed()) { - throw exit_success{}; - } else { - logger.info("Reloading application..."); - } - - } catch (const exit_success& term) { - exit_code = EXIT_SUCCESS; - quit = true; - } catch (const exit_failure& term) { - exit_code = EXIT_FAILURE; - quit = true; - } catch (const exception& err) { - logger.err(err.what()); - exit_code = EXIT_FAILURE; - quit = true; + if ((connection = xutils::get_connection()) == nullptr) { + logger.err("A connection to X could not be established... "); + throw exit_failure{}; } + + xfd = xcb_get_file_descriptor(connection); + + //================================================== + // Parse command line arguments + //================================================== + string scriptname{argv[0]}; + vector args(argv + 1, argv + argc); + + cliparser cli{configure_cliparser(scriptname, opts).create()}; + cli.process_input(args); + + if (cli.has("quiet")) { + logger.verbosity(loglevel::ERROR); + } else if (cli.has("log")) { + logger.verbosity(cli.get("log")); + } + + if (cli.has("help")) { + cli.usage(); + throw exit_success{}; + } else if (cli.has("version")) { + print_build_info(version_details(args)); + throw exit_success{}; + } else if (args.empty() || args[0][0] == '-') { + cli.usage(); + throw exit_failure{}; + } + + //================================================== + // Load user configuration + //================================================== + config& conf{configure_config().create()}; + + if (cli.has("config")) { + conf.load(cli.get("config"), args[0]); + } else if (env_util::has("XDG_CONFIG_HOME")) { + conf.load(env_util::get("XDG_CONFIG_HOME") + "/polybar/config", args[0]); + } else if (env_util::has("HOME")) { + conf.load(env_util::get("HOME") + "/.config/polybar/config", args[0]); + } else { + throw application_error("Define configuration using --config=PATH"); + } + + //================================================== + // Dump requested data + //================================================== + if (cli.has("dump")) { + std::cout << conf.get(conf.bar_section(), cli.get("dump")) << std::endl; + throw exit_success{}; + } + + //================================================== + // Create config watch if we should track changes + //================================================== + inotify_util::watch_t watch; + + if (cli.has("reload")) { + watch = inotify_util::make_watch(conf.filepath()); + } + + //================================================== + // Create controller + //================================================== + auto ctrl = configure_controller(watch).create>(); + + ctrl->bootstrap(cli.has("stdout"), cli.has("print-wmname")); + + if (cli.has("print-wmname")) { + throw exit_success{}; + } + + //================================================== + // Run application + //================================================== + if (!ctrl->run()) { + reload = true; + } + } catch (const exit_success& term) { + exit_code = EXIT_SUCCESS; + } catch (const exit_failure& term) { + exit_code = EXIT_FAILURE; + } catch (const exception& err) { + logger.err(err.what()); + exit_code = EXIT_FAILURE; } - logger.trace("Close connection to X server"); - ewmh_util::dealloc(); - xcb_disconnect(connection); - close(xfd); + if (xfd != 0) { + close(xfd); + } - logger.info("Reached end of application..."); + if (!reload) { + logger.info("Reached end of application..."); + return exit_code; + } - return exit_code; + try { + logger.info("Reload application..."); + process_util::exec(argv[0], argv); + } catch (const system_error& err) { + logger.err("execlp() failed (%s)", strerror(errno)); + } + + return EXIT_FAILURE; } diff --git a/src/utils/process.cpp b/src/utils/process.cpp index 0111a764..39817b23 100644 --- a/src/utils/process.cpp +++ b/src/utils/process.cpp @@ -22,6 +22,14 @@ namespace process_util { return pid == 0; } + /** + * Replace current process + */ + void exec(char* cmd, char** args) { + execvp(cmd, args); + throw system_error("execvp() failed"); + } + /** * Replace process with command */ @@ -38,11 +46,8 @@ namespace process_util { for (auto&& argument : args) { c_args.emplace_back(const_cast(argument.c_str())); } - c_args.emplace_back(nullptr); - execvp(c_args[0], c_args.data()); - - throw system_error("Failed to execute command"); + exec(c_args[0], c_args.data()); } /**