mirror of
https://github.com/polybar/polybar.git
synced 2025-02-17 15:55:20 -05:00
fix(script): Rerun tail script when done
- Improve handling of command life time proc - Restart tail command on successful completion - Should fix jaagr/lemonbuddy#105
This commit is contained in:
parent
20ca754629
commit
7e960a3966
3 changed files with 88 additions and 88 deletions
|
@ -76,8 +76,8 @@ class controller {
|
||||||
m_log.trace("controller: Stop modules");
|
m_log.trace("controller: Stop modules");
|
||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
module->on_update.disconnect(this, &controller::on_module_update);
|
module->on_update.clear();
|
||||||
module->on_stop.disconnect(this, &controller::on_module_stop);
|
module->on_stop.clear();
|
||||||
module->stop();
|
module->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ class controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("controller: Deconstruct bar instance");
|
m_log.trace("controller: Deconstruct bar instance");
|
||||||
g_signals::bar::action_click.disconnect(this, &controller::on_module_click);
|
g_signals::bar::action_click.clear();
|
||||||
m_bar.reset();
|
m_bar.reset();
|
||||||
|
|
||||||
m_log.trace("controller: Interrupt X event loop");
|
m_log.trace("controller: Interrupt X event loop");
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
LEMONBUDDY_NS
|
LEMONBUDDY_NS
|
||||||
|
|
||||||
#define SHELL_CMD "/usr/bin/env\nsh\n-c\n"
|
#define SHELL_CMD "/usr/bin/env\nsh\n-c\n%cmd%"
|
||||||
#define OUTPUT_ACTION(BUTTON) \
|
#define OUTPUT_ACTION(BUTTON) \
|
||||||
if (!m_actions[BUTTON].empty()) \
|
if (!m_actions[BUTTON].empty()) \
|
||||||
m_builder->cmd(BUTTON, string_util::replace_all(m_actions[BUTTON], "%counter%", counter_str))
|
m_builder->cmd(BUTTON, string_util::replace_all(m_actions[BUTTON], "%counter%", counter_str))
|
||||||
|
@ -18,7 +18,8 @@ namespace modules {
|
||||||
void setup() {
|
void setup() {
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, {TAG_OUTPUT});
|
m_formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, {TAG_OUTPUT});
|
||||||
|
|
||||||
// Load configuration values {{{
|
// Load configuration values
|
||||||
|
|
||||||
REQ_CONFIG_VALUE(name(), m_exec, "exec");
|
REQ_CONFIG_VALUE(name(), m_exec, "exec");
|
||||||
GET_CONFIG_VALUE(name(), m_tail, "tail");
|
GET_CONFIG_VALUE(name(), m_tail, "tail");
|
||||||
GET_CONFIG_VALUE(name(), m_maxlen, "maxlen");
|
GET_CONFIG_VALUE(name(), m_maxlen, "maxlen");
|
||||||
|
@ -30,113 +31,99 @@ namespace modules {
|
||||||
m_actions[mousebtn::SCROLL_UP] = m_conf.get<string>(name(), "scroll-up", "");
|
m_actions[mousebtn::SCROLL_UP] = m_conf.get<string>(name(), "scroll-up", "");
|
||||||
m_actions[mousebtn::SCROLL_DOWN] = m_conf.get<string>(name(), "scroll-down", "");
|
m_actions[mousebtn::SCROLL_DOWN] = m_conf.get<string>(name(), "scroll-down", "");
|
||||||
|
|
||||||
if (!m_tail) {
|
m_interval = interval_t{m_conf.get<float>(name(), "interval", 0.0f)};
|
||||||
m_interval = interval_t{m_conf.get<float>(name(), "interval", m_interval.count())};
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
// Execute the tail command {{{
|
|
||||||
if (m_tail) {
|
|
||||||
try {
|
|
||||||
auto exec = string_util::replace_all(m_exec, "%counter%", to_string(++m_counter));
|
|
||||||
m_log.trace("%s: Executing '%s'", name(), exec);
|
|
||||||
|
|
||||||
m_command = command_util::make_command(SHELL_CMD + exec);
|
|
||||||
m_command->exec(false);
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("%s: Failed to execute tail command, stopping module..", name());
|
|
||||||
m_log.err("%s: %s", name(), err.what());
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
// Put the module in stopped state {{{
|
wakeup();
|
||||||
event_module::stop();
|
enable(false);
|
||||||
// }}}
|
m_command.reset();
|
||||||
// Terminate running command {{{
|
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
||||||
try {
|
wakeup();
|
||||||
if (m_tail && m_command)
|
}
|
||||||
m_command.reset();
|
|
||||||
} catch (const std::exception& err) {
|
void idle() {
|
||||||
m_log.err("%s: %s", name(), err.what());
|
if (!enabled())
|
||||||
}
|
sleep(100ms);
|
||||||
// }}}
|
if (!m_tail)
|
||||||
|
sleep(m_interval);
|
||||||
|
else if (!m_command || !m_command->is_running())
|
||||||
|
sleep(m_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_event() {
|
bool has_event() {
|
||||||
// Handle non-tailing command {{{
|
// Non tail commands should always run
|
||||||
if (!m_tail) {
|
if (!m_tail)
|
||||||
sleep(m_interval);
|
|
||||||
return enabled();
|
|
||||||
}
|
|
||||||
// }}}
|
|
||||||
// Handle tailing command {{{
|
|
||||||
if (!m_command || !m_command->is_running()) {
|
|
||||||
m_log.warn("%s: Tail command finished, stopping module...", name());
|
|
||||||
stop();
|
|
||||||
return false;
|
|
||||||
} else if ((m_output = m_command->readline()) != m_prev) {
|
|
||||||
m_prev = m_output;
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
|
if (!enabled())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!m_command || !m_command->is_running()) {
|
||||||
|
auto exec = string_util::replace_all(m_exec, "%counter%", to_string(++m_counter));
|
||||||
|
m_log.trace("%s: Executing '%s'", name(), exec);
|
||||||
|
|
||||||
|
m_command = command_util::make_command(string_util::replace(SHELL_CMD, "%cmd%", exec));
|
||||||
|
m_command->exec(false);
|
||||||
|
}
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("%s: %s", name(), err.what());
|
||||||
|
throw module_error(name() + ": Failed to execute tail command, stopping module...");
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
|
if (!m_command)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((m_output = m_command->readline()) == m_prev)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_prev = m_output;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update() {
|
bool update() {
|
||||||
// Handle tailing command {{{
|
// Tailing commands always update
|
||||||
if (m_tail)
|
if (m_tail)
|
||||||
return true;
|
return true;
|
||||||
// }}}
|
|
||||||
// Handle non-tailing command {{{
|
|
||||||
try {
|
try {
|
||||||
auto exec = string_util::replace_all(m_exec, "%counter%", to_string(++m_counter));
|
auto exec = string_util::replace_all(m_exec, "%counter%", to_string(++m_counter));
|
||||||
auto cmd = command_util::make_command(SHELL_CMD + exec);
|
auto cmd = command_util::make_command(string_util::replace(SHELL_CMD, "%cmd%", exec));
|
||||||
|
|
||||||
m_log.trace("%s: Executing '%s'", name(), exec);
|
m_log.trace("%s: Executing '%s'", name(), exec);
|
||||||
|
|
||||||
cmd->exec();
|
cmd->exec();
|
||||||
cmd->tail([this](string contents) { m_output = contents; });
|
cmd->tail([this](string contents) { m_output = contents; });
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
m_log.err("%s: Failed to execute command, stopping module..", name());
|
|
||||||
m_log.err("%s: %s", name(), err.what());
|
m_log.err("%s: %s", name(), err.what());
|
||||||
stop();
|
throw module_error(name() + ": Failed to execute command, stopping module...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_output == m_prev)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (m_output != m_prev) {
|
m_prev = m_output;
|
||||||
m_prev = m_output;
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
// }}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string get_output() {
|
string get_output() {
|
||||||
if (m_output.empty())
|
if (m_output.empty())
|
||||||
return " ";
|
return " ";
|
||||||
|
|
||||||
// Truncate output to the defined max length {{{
|
// Truncate output to the defined max length
|
||||||
|
|
||||||
if (m_maxlen > 0 && m_output.length() > m_maxlen) {
|
if (m_maxlen > 0 && m_output.length() > m_maxlen) {
|
||||||
m_output.erase(m_maxlen);
|
m_output.erase(m_maxlen);
|
||||||
m_output += m_ellipsis ? "..." : "";
|
m_output += m_ellipsis ? "..." : "";
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
// Add mousebtn command handlers {{{
|
|
||||||
auto counter_str = to_string(m_counter);
|
|
||||||
|
|
||||||
|
auto counter_str = to_string(m_counter);
|
||||||
OUTPUT_ACTION(mousebtn::LEFT);
|
OUTPUT_ACTION(mousebtn::LEFT);
|
||||||
OUTPUT_ACTION(mousebtn::MIDDLE);
|
OUTPUT_ACTION(mousebtn::MIDDLE);
|
||||||
OUTPUT_ACTION(mousebtn::RIGHT);
|
OUTPUT_ACTION(mousebtn::RIGHT);
|
||||||
OUTPUT_ACTION(mousebtn::SCROLL_UP);
|
OUTPUT_ACTION(mousebtn::SCROLL_UP);
|
||||||
OUTPUT_ACTION(mousebtn::SCROLL_DOWN);
|
OUTPUT_ACTION(mousebtn::SCROLL_DOWN);
|
||||||
// }}}
|
|
||||||
|
|
||||||
m_builder->node(module::get_output());
|
m_builder->node(module::get_output());
|
||||||
|
|
||||||
return m_builder->flush();
|
return m_builder->flush();
|
||||||
|
@ -156,7 +143,7 @@ namespace modules {
|
||||||
|
|
||||||
string m_exec;
|
string m_exec;
|
||||||
bool m_tail = false;
|
bool m_tail = false;
|
||||||
interval_t m_interval = 1s;
|
interval_t m_interval = 0s;
|
||||||
size_t m_maxlen = 0;
|
size_t m_maxlen = 0;
|
||||||
bool m_ellipsis = true;
|
bool m_ellipsis = true;
|
||||||
map<mousebtn, string> m_actions;
|
map<mousebtn, string> m_actions;
|
||||||
|
|
|
@ -60,15 +60,8 @@ namespace command_util {
|
||||||
}
|
}
|
||||||
|
|
||||||
~command() {
|
~command() {
|
||||||
if (is_running()) {
|
if (is_running())
|
||||||
try {
|
terminate();
|
||||||
m_log.trace("command: Sending SIGTERM to running child process (%d)", m_forkpid);
|
|
||||||
killpg(m_forkpid, SIGTERM);
|
|
||||||
wait();
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("command: %s", err.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_stdin[PIPE_READ] > 0)
|
if (m_stdin[PIPE_READ] > 0)
|
||||||
close(m_stdin[PIPE_READ]);
|
close(m_stdin[PIPE_READ]);
|
||||||
|
@ -119,13 +112,30 @@ namespace command_util {
|
||||||
if ((m_stdout[PIPE_WRITE] = close(m_stdout[PIPE_WRITE])) == -1)
|
if ((m_stdout[PIPE_WRITE] = close(m_stdout[PIPE_WRITE])) == -1)
|
||||||
throw command_strerror("Failed to close fd");
|
throw command_strerror("Failed to close fd");
|
||||||
|
|
||||||
if (wait_for_completion)
|
if (wait_for_completion) {
|
||||||
return wait();
|
auto status = wait();
|
||||||
|
m_forkpid = -1;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terminate() {
|
||||||
|
try {
|
||||||
|
if (is_running()) {
|
||||||
|
m_log.trace("command: Sending SIGTERM to running child process (%d)", m_forkpid);
|
||||||
|
killpg(m_forkpid, SIGTERM);
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
} catch (const command_error& err) {
|
||||||
|
m_log.warn("%s", err.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_forkpid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for the child processs to finish
|
* Wait for the child processs to finish
|
||||||
*/
|
*/
|
||||||
|
@ -133,11 +143,12 @@ namespace command_util {
|
||||||
auto waitflags = WCONTINUED | WUNTRACED;
|
auto waitflags = WCONTINUED | WUNTRACED;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (process_util::wait_for_completion(m_forkpid, &m_forkstatus, waitflags) == -1)
|
process_util::wait_for_completion(m_forkpid, &m_forkstatus, waitflags);
|
||||||
throw command_error("Process did not finish successfully");
|
|
||||||
|
|
||||||
if (WIFEXITED(m_forkstatus))
|
if (WIFEXITED(m_forkstatus) && m_forkstatus > 0)
|
||||||
m_log.trace("command: Exited with status %d", WEXITSTATUS(m_forkstatus));
|
m_log.warn("command: Exited with failed status %d", WEXITSTATUS(m_forkstatus));
|
||||||
|
else if (WIFEXITED(m_forkstatus))
|
||||||
|
m_log.warn("command: Exited with status %d", WEXITSTATUS(m_forkstatus));
|
||||||
else if (WIFSIGNALED(m_forkstatus))
|
else if (WIFSIGNALED(m_forkstatus))
|
||||||
m_log.trace("command: killed by signal %d", WTERMSIG(m_forkstatus));
|
m_log.trace("command: killed by signal %d", WTERMSIG(m_forkstatus));
|
||||||
else if (WIFSTOPPED(m_forkstatus))
|
else if (WIFSTOPPED(m_forkstatus))
|
||||||
|
@ -197,7 +208,9 @@ namespace command_util {
|
||||||
* Check if command is running
|
* Check if command is running
|
||||||
*/
|
*/
|
||||||
bool is_running() {
|
bool is_running() {
|
||||||
return process_util::wait_for_completion_nohang(m_forkpid, &m_forkstatus) > -1;
|
if (m_forkpid > 0)
|
||||||
|
return process_util::wait_for_completion_nohang(m_forkpid, &m_forkstatus) > -1;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue