fix: Replace process on reload
This commit is contained in:
parent
0f91d3d8df
commit
086e498388
@ -37,9 +37,7 @@ class controller {
|
|||||||
~controller();
|
~controller();
|
||||||
|
|
||||||
void bootstrap(bool writeback = false, bool dump_wmname = false);
|
void bootstrap(bool writeback = false, bool dump_wmname = false);
|
||||||
|
bool run();
|
||||||
void run();
|
|
||||||
bool completed();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void install_sigmask();
|
void install_sigmask();
|
||||||
|
@ -8,6 +8,7 @@ namespace process_util {
|
|||||||
bool in_parent_process(pid_t pid);
|
bool in_parent_process(pid_t pid);
|
||||||
bool in_forked_process(pid_t pid);
|
bool in_forked_process(pid_t pid);
|
||||||
|
|
||||||
|
void exec(char* cmd, char** args);
|
||||||
void exec(const string& cmd);
|
void exec(const string& cmd);
|
||||||
|
|
||||||
pid_t wait_for_completion(pid_t process_id, int* status_addr, int waitflags = 0);
|
pid_t wait_for_completion(pid_t process_id, int* status_addr, int waitflags = 0);
|
||||||
|
@ -118,6 +118,7 @@ controller::~controller() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_connection.flush();
|
m_connection.flush();
|
||||||
|
m_connection.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,7 +179,7 @@ void controller::bootstrap(bool writeback, bool dump_wmname) {
|
|||||||
/**
|
/**
|
||||||
* Launch the controller
|
* Launch the controller
|
||||||
*/
|
*/
|
||||||
void controller::run() {
|
bool controller::run() {
|
||||||
assert(!m_connection.connection_has_error());
|
assert(!m_connection.connection_has_error());
|
||||||
|
|
||||||
m_log.info("Starting application");
|
m_log.info("Starting application");
|
||||||
@ -235,12 +236,7 @@ void controller::run() {
|
|||||||
m_log.trace("controller: Removing config watch");
|
m_log.trace("controller: Removing config watch");
|
||||||
m_confwatch->remove(true);
|
m_confwatch->remove(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get completion state
|
|
||||||
*/
|
|
||||||
bool controller::completed() {
|
|
||||||
return !m_running && !m_reload;
|
return !m_running && !m_reload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
221
src/main.cpp
221
src/main.cpp
@ -10,6 +10,7 @@
|
|||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "utils/env.hpp"
|
#include "utils/env.hpp"
|
||||||
#include "utils/inotify.hpp"
|
#include "utils/inotify.hpp"
|
||||||
|
#include "utils/process.hpp"
|
||||||
#include "x11/ewmh.hpp"
|
#include "x11/ewmh.hpp"
|
||||||
#include "x11/xutils.hpp"
|
#include "x11/xutils.hpp"
|
||||||
|
|
||||||
@ -20,7 +21,8 @@ struct exit_failure {};
|
|||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
uint8_t exit_code{EXIT_SUCCESS};
|
uint8_t exit_code{EXIT_SUCCESS};
|
||||||
stateflag quit{false};
|
bool reload{false};
|
||||||
|
int xfd;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const command_line::options opts{
|
const command_line::options opts{
|
||||||
@ -38,119 +40,120 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
logger& logger{configure_logger<decltype(logger)>(loglevel::WARNING).create<decltype(logger)>()};
|
logger& logger{configure_logger<decltype(logger)>(loglevel::WARNING).create<decltype(logger)>()};
|
||||||
|
|
||||||
//==================================================
|
try {
|
||||||
// Connect to X server
|
//==================================================
|
||||||
//==================================================
|
// Connect to X server
|
||||||
XInitThreads();
|
//==================================================
|
||||||
|
XInitThreads();
|
||||||
|
|
||||||
xcb_connection_t* connection{nullptr};
|
xcb_connection_t* connection{nullptr};
|
||||||
|
|
||||||
if ((connection = xutils::get_connection()) == nullptr) {
|
if ((connection = xutils::get_connection()) == nullptr) {
|
||||||
logger.err("A connection to X could not be established... ");
|
logger.err("A connection to X could not be established... ");
|
||||||
throw exit_failure{};
|
throw exit_failure{};
|
||||||
}
|
|
||||||
|
|
||||||
int xfd{xcb_get_file_descriptor(connection)};
|
|
||||||
|
|
||||||
while (!quit) {
|
|
||||||
try {
|
|
||||||
//==================================================
|
|
||||||
// Parse command line arguments
|
|
||||||
//==================================================
|
|
||||||
vector<string> args(argv + 1, argv + argc);
|
|
||||||
cliparser cli{configure_cliparser<decltype(cli)>(argv[0], opts).create<decltype(cli)>()};
|
|
||||||
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<decltype(conf)>().create<decltype(conf)>()};
|
|
||||||
|
|
||||||
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<string>(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<unique_ptr<controller>>();
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xfd = xcb_get_file_descriptor(connection);
|
||||||
|
|
||||||
|
//==================================================
|
||||||
|
// Parse command line arguments
|
||||||
|
//==================================================
|
||||||
|
string scriptname{argv[0]};
|
||||||
|
vector<string> args(argv + 1, argv + argc);
|
||||||
|
|
||||||
|
cliparser cli{configure_cliparser<decltype(cli)>(scriptname, opts).create<decltype(cli)>()};
|
||||||
|
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<decltype(conf)>().create<decltype(conf)>()};
|
||||||
|
|
||||||
|
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<string>(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<unique_ptr<controller>>();
|
||||||
|
|
||||||
|
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");
|
if (xfd != 0) {
|
||||||
ewmh_util::dealloc();
|
close(xfd);
|
||||||
xcb_disconnect(connection);
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ namespace process_util {
|
|||||||
return pid == 0;
|
return pid == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace current process
|
||||||
|
*/
|
||||||
|
void exec(char* cmd, char** args) {
|
||||||
|
execvp(cmd, args);
|
||||||
|
throw system_error("execvp() failed");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace process with command
|
* Replace process with command
|
||||||
*/
|
*/
|
||||||
@ -38,11 +46,8 @@ namespace process_util {
|
|||||||
for (auto&& argument : args) {
|
for (auto&& argument : args) {
|
||||||
c_args.emplace_back(const_cast<char*>(argument.c_str()));
|
c_args.emplace_back(const_cast<char*>(argument.c_str()));
|
||||||
}
|
}
|
||||||
c_args.emplace_back(nullptr);
|
|
||||||
|
|
||||||
execvp(c_args[0], c_args.data());
|
exec(c_args[0], c_args.data());
|
||||||
|
|
||||||
throw system_error("Failed to execute command");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user