fix(script): Prevent stalling during shutdown

If a script module is waiting on a non-tailed script to finish, polybar
cannot shut down until the script has terminted.
To remedy this, we use the same polling loop as for tailed scripts which
checks if it needs to terminate after every iteration.
This commit is contained in:
patrick96 2022-03-03 23:38:51 +01:00 committed by Patrick Ziegler
parent 0b24080336
commit c655adea93
2 changed files with 23 additions and 3 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- `tray-offset-x`, `tray-offset-y`, `offset-x`, and `offset-y` were mistakenly capped below at 0 ([`#2620`](https://github.com/polybar/polybar/pull/2620)) - `tray-offset-x`, `tray-offset-y`, `offset-x`, and `offset-y` were mistakenly capped below at 0 ([`#2620`](https://github.com/polybar/polybar/pull/2620))
- `custom/script`: Polybar shutdown being stalled by hanging script ([`#2621`](https://github.com/polybar/polybar/pull/2621))
## [3.6.0] - 2022-03-01 ## [3.6.0] - 2022-03-01
### Breaking ### Breaking

View File

@ -96,16 +96,35 @@ script_runner::interval script_runner::run() {
auto cmd = command_util::make_command<output_policy::REDIRECTED>(exec); auto cmd = command_util::make_command<output_policy::REDIRECTED>(exec);
try { try {
cmd->exec(true, m_env); cmd->exec(false, m_env);
} catch (const exception& err) { } catch (const exception& err) {
m_log.err("script_runner: %s", err.what()); m_log.err("script_runner: %s", err.what());
throw modules::module_error("Failed to execute command, stopping module..."); throw modules::module_error("Failed to execute command, stopping module...");
} }
m_exit_status = cmd->get_exit_status();
int fd = cmd->get_stdout(PIPE_READ); int fd = cmd->get_stdout(PIPE_READ);
assert(fd != -1); assert(fd != -1);
bool changed = io_util::poll_read(fd) && set_output(cmd->readline());
bool changed = false;
bool got_output = false;
while (!m_stopping && cmd->is_running() && !io_util::poll(fd, POLLHUP, 0)) {
/**
* For non-tailed scripts, we only use the first line. However, to ensure interruptability when the module shuts
* down, we still need to continue polling.
*/
if (io_util::poll_read(fd, 25) && !got_output) {
changed = set_output(cmd->readline());
got_output = true;
}
}
if (m_stopping) {
cmd->terminate();
return 0s;
}
m_exit_status = cmd->wait();
if (!changed && m_exit_status != 0) { if (!changed && m_exit_status != 0) {
clear_output(); clear_output();