custom-graph: fix worker crash, JSON UTF-8 validation, SIGRTMIN guard
Bring src/modules/custom_graph.cpp in line with the hardened custom.cpp: - continuousWorker: on the restart path, an open() failure threw std::runtime_error out of the SleeperThread lambda, which escaped the thread and called std::terminate, killing all of Waybar. Log the error and stop the worker gracefully instead of throwing. - parseOutputJson: validate/make_valid the text/alt/tooltip JSON string fields before they reach fmt markup / set_tooltip_markup. Invalid UTF-8 from a script otherwise aborts the bar in g_utf8_* (parseOutputRaw already validated the same way). - refresh: wrap the SIGRTMIN-based signal check in #ifdef SIGRTMIN so the module builds on platforms without SIGRTMIN (e.g. some BSDs). Fixes a std::terminate crash on continuous-exec restart failure, an invalid-UTF-8 bar abort via JSON output, and a build break on platforms lacking SIGRTMIN.
This commit is contained in:
@@ -99,7 +99,13 @@ void waybar::modules::CustomGraph::continuousWorker() {
|
||||
thread_.sleep_for(std::chrono::seconds(config_["restart-interval"].asUInt()));
|
||||
fp_ = util::command::open(cmd, pid_, output_name_);
|
||||
if (!fp_) {
|
||||
throw std::runtime_error("Unable to open " + cmd);
|
||||
// Letting this exception escape the SleeperThread would call
|
||||
// std::terminate and kill all of Waybar. Degrade gracefully instead.
|
||||
output_ = {1, ""};
|
||||
dp.emit();
|
||||
spdlog::error("Unable to restart {}: unable to open {}", name_, cmd);
|
||||
thread_.stop();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
thread_.stop();
|
||||
@@ -139,9 +145,11 @@ void waybar::modules::CustomGraph::waitingWorker() {
|
||||
}
|
||||
|
||||
void waybar::modules::CustomGraph::refresh(int sig) {
|
||||
#ifdef SIGRTMIN
|
||||
if (config_["signal"].isInt() && sig == SIGRTMIN + config_["signal"].asInt()) {
|
||||
thread_.wake_up();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void waybar::modules::CustomGraph::handleEvent() {
|
||||
@@ -268,22 +276,32 @@ void waybar::modules::CustomGraph::parseOutputJson() {
|
||||
std::istringstream output(output_.out);
|
||||
std::string line;
|
||||
class_.clear();
|
||||
// A script can emit invalid UTF-8; passing it unchecked to Pango/GTK aborts
|
||||
// the whole bar in g_utf8_* (see parseOutputRaw, which validates the same way).
|
||||
auto sanitize = [](const std::string& s) -> Glib::ustring {
|
||||
Glib::ustring value = s;
|
||||
if (!value.validate()) {
|
||||
value = value.make_valid();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
while (getline(output, line)) {
|
||||
auto parsed = parser_.parse(line);
|
||||
if (config_["escape"].isBool() && config_["escape"].asBool()) {
|
||||
text_ = Glib::Markup::escape_text(parsed["text"].asString());
|
||||
const bool escape = config_["escape"].isBool() && config_["escape"].asBool();
|
||||
if (escape) {
|
||||
text_ = Glib::Markup::escape_text(sanitize(parsed["text"].asString()));
|
||||
} else {
|
||||
text_ = parsed["text"].asString();
|
||||
text_ = sanitize(parsed["text"].asString());
|
||||
}
|
||||
if (config_["escape"].isBool() && config_["escape"].asBool()) {
|
||||
alt_ = Glib::Markup::escape_text(parsed["alt"].asString());
|
||||
if (escape) {
|
||||
alt_ = Glib::Markup::escape_text(sanitize(parsed["alt"].asString()));
|
||||
} else {
|
||||
alt_ = parsed["alt"].asString();
|
||||
alt_ = sanitize(parsed["alt"].asString());
|
||||
}
|
||||
if (config_["escape"].isBool() && config_["escape"].asBool()) {
|
||||
tooltip_ = Glib::Markup::escape_text(parsed["tooltip"].asString());
|
||||
if (escape) {
|
||||
tooltip_ = Glib::Markup::escape_text(sanitize(parsed["tooltip"].asString()));
|
||||
} else {
|
||||
tooltip_ = parsed["tooltip"].asString();
|
||||
tooltip_ = sanitize(parsed["tooltip"].asString());
|
||||
}
|
||||
if (parsed["class"].isString()) {
|
||||
class_.push_back(parsed["class"].asString());
|
||||
|
||||
Reference in New Issue
Block a user