From f717abc004de4c0319f086acd3f5fb56a6ef5ff227a8e17154034c4aeb275d9d Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Mon, 15 Mar 2021 11:53:01 +0000 Subject: [PATCH] Accepting request 879138 from home:mcepl:branches:X11:Wayland - Add 1015-rfkill_code_refactoring.patch to avoid gh#Alexays/Waybar#994 and boo#1183499. OBS-URL: https://build.opensuse.org/request/show/879138 OBS-URL: https://build.opensuse.org/package/show/X11:Wayland/waybar?expand=0&rev=53 --- 1015-rfkill_code_refactoring.patch | 297 +++++++++++++++++++++++++++++ waybar.changes | 6 + waybar.spec | 4 +- 3 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 1015-rfkill_code_refactoring.patch diff --git a/1015-rfkill_code_refactoring.patch b/1015-rfkill_code_refactoring.patch new file mode 100644 index 0000000..98d417e --- /dev/null +++ b/1015-rfkill_code_refactoring.patch @@ -0,0 +1,297 @@ +From 40f4dc9ecf26a8d9cd8d33b9bc88ff4dd6b3e508 Mon Sep 17 00:00:00 2001 +From: Aleksei Bavshin +Date: Mon, 1 Feb 2021 18:50:45 -0800 +Subject: [PATCH 1/6] fix(rfkill): accept events larger than v1 event size + +Kernel 5.11 added one more field to the `struct rfkill_event` and broke +unnecessarily strict check in `rfkill.cpp`. According to `linux/rfkill.h`, +we must accept events at least as large as v1 event size and should be +prepared to get additional fields at the end of a v1 event structure. +--- + include/modules/bluetooth.hpp | 8 ---- + include/modules/network.hpp | 2 - + include/util/rfkill.hpp | 15 ++++++-- + man/waybar-bluetooth.5.scd | 6 --- + src/modules/bluetooth.cpp | 36 ++++--------------- + src/modules/network.cpp | 19 ++++------ + src/util/rfkill.cpp | 76 ++++++++++++++++++++++-------------------- + 7 files changed, 67 insertions(+), 95 deletions(-) + +--- a/include/modules/bluetooth.hpp ++++ b/include/modules/bluetooth.hpp +@@ -1,10 +1,6 @@ + #pragma once + +-#include + #include "ALabel.hpp" +- +-#include +-#include "util/sleeper_thread.hpp" + #include "util/rfkill.hpp" + + namespace waybar::modules { +@@ -16,10 +12,6 @@ class Bluetooth : public ALabel { + auto update() -> void; + + private: +- std::string status_; +- util::SleeperThread thread_; +- util::SleeperThread intervall_thread_; +- + util::Rfkill rfkill_; + }; + +--- a/include/modules/network.hpp ++++ b/include/modules/network.hpp +@@ -75,8 +75,6 @@ class Network : public ALabel { + util::SleeperThread thread_; + util::SleeperThread thread_timer_; + #ifdef WANT_RFKILL +- util::SleeperThread thread_rfkill_; +- + util::Rfkill rfkill_; + #endif + }; +--- a/include/util/rfkill.hpp ++++ b/include/util/rfkill.hpp +@@ -1,19 +1,26 @@ + #pragma once + ++#include + #include ++#include ++#include + + namespace waybar::util { + +-class Rfkill { ++class Rfkill : public sigc::trackable { + public: + Rfkill(enum rfkill_type rfkill_type); +- ~Rfkill() = default; +- void waitForEvent(); ++ ~Rfkill(); + bool getState() const; + ++ sigc::signal on_update; ++ + private: + enum rfkill_type rfkill_type_; +- int state_ = 0; ++ bool state_ = false; ++ int fd_ = -1; ++ ++ bool on_event(Glib::IOCondition cond); + }; + + } // namespace waybar::util +--- a/man/waybar-bluetooth.5.scd ++++ b/man/waybar-bluetooth.5.scd +@@ -12,11 +12,6 @@ The *bluetooth* module displays informat + + Addressed by *bluetooth* + +-*interval*: ++ +- typeof: integer ++ +- default: 60 ++ +- The interval in which the bluetooth state gets updated. +- + *format*: ++ + typeof: string ++ + default: *{icon}* ++ +@@ -80,7 +75,6 @@ Addressed by *bluetooth* + "bluetooth": { + "format": "{icon}", + "format-alt": "bluetooth: {status}", +- "interval": 30, + "format-icons": { + "enabled": "", + "disabled": "" +--- a/src/modules/bluetooth.cpp ++++ b/src/modules/bluetooth.cpp +@@ -1,45 +1,25 @@ + #include "modules/bluetooth.hpp" +-#include "util/rfkill.hpp" +-#include +-#include ++ ++#include + + waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& config) +- : ALabel(config, "bluetooth", id, "{icon}", 10), +- status_("disabled"), +- rfkill_{RFKILL_TYPE_BLUETOOTH} { +- thread_ = [this] { +- dp.emit(); +- rfkill_.waitForEvent(); +- }; +- intervall_thread_ = [this] { +- auto now = std::chrono::system_clock::now(); +- auto timeout = std::chrono::floor(now + interval_); +- auto diff = std::chrono::seconds(timeout.time_since_epoch().count() % interval_.count()); +- thread_.sleep_until(timeout - diff); +- dp.emit(); +- }; ++ : ALabel(config, "bluetooth", id, "{icon}", 10), rfkill_{RFKILL_TYPE_BLUETOOTH} { ++ rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update))); + } + + auto waybar::modules::Bluetooth::update() -> void { +- if (rfkill_.getState()) { +- status_ = "disabled"; +- } else { +- status_ = "enabled"; +- } ++ std::string status = rfkill_.getState() ? "disabled" : "enabled"; + + label_.set_markup( +- fmt::format( +- format_, +- fmt::arg("status", status_), +- fmt::arg("icon", getIcon(0, status_)))); ++ fmt::format(format_, fmt::arg("status", status), fmt::arg("icon", getIcon(0, status)))); + + if (tooltipEnabled()) { + if (config_["tooltip-format"].isString()) { + auto tooltip_format = config_["tooltip-format"].asString(); +- auto tooltip_text = fmt::format(tooltip_format, status_); ++ auto tooltip_text = fmt::format(tooltip_format, status); + label_.set_tooltip_text(tooltip_text); + } else { +- label_.set_tooltip_text(status_); ++ label_.set_tooltip_text(status); + } + } + } +--- a/src/modules/network.cpp ++++ b/src/modules/network.cpp +@@ -212,18 +212,15 @@ void waybar::modules::Network::worker() + thread_timer_.sleep_for(interval_); + }; + #ifdef WANT_RFKILL +- thread_rfkill_ = [this] { +- rfkill_.waitForEvent(); +- { +- std::lock_guard lock(mutex_); +- if (ifid_ > 0) { +- getInfo(); +- dp.emit(); +- } +- } +- }; ++ rfkill_.on_update.connect([this](auto &) { ++ /* If we are here, it's likely that the network thread already holds the mutex and will be ++ * holding it for a next few seconds. ++ * Let's delegate the update to the timer thread instead of blocking the main thread. ++ */ ++ thread_timer_.wake_up(); ++ }); + #else +- spdlog::warn("Waybar has been built without rfkill support."); ++ spdlog::warn("Waybar has been built without rfkill support."); + #endif + thread_ = [this] { + std::array events{}; +--- a/src/util/rfkill.cpp ++++ b/src/util/rfkill.cpp +@@ -19,60 +19,64 @@ + #include "util/rfkill.hpp" + + #include ++#include + #include +-#include +-#include ++#include + #include + + #include +-#include +-#include + +-waybar::util::Rfkill::Rfkill(const enum rfkill_type rfkill_type) : rfkill_type_(rfkill_type) {} +- +-void waybar::util::Rfkill::waitForEvent() { +- struct rfkill_event event; +- struct pollfd p; +- ssize_t len; +- int fd, n; +- +- fd = open("/dev/rfkill", O_RDONLY); +- if (fd < 0) { +- throw std::runtime_error("Can't open RFKILL control device"); ++waybar::util::Rfkill::Rfkill(const enum rfkill_type rfkill_type) : rfkill_type_(rfkill_type) { ++ fd_ = open("/dev/rfkill", O_RDONLY); ++ if (fd_ < 0) { ++ spdlog::error("Can't open RFKILL control device"); ++ return; ++ } ++ int rc = fcntl(fd_, F_SETFL, O_NONBLOCK); ++ if (rc < 0) { ++ spdlog::error("Can't set RFKILL control device to non-blocking: {}", errno); ++ close(fd_); ++ fd_ = -1; + return; + } ++ Glib::signal_io().connect( ++ sigc::mem_fun(*this, &Rfkill::on_event), fd_, Glib::IO_IN | Glib::IO_ERR | Glib::IO_HUP); ++} + +- memset(&p, 0, sizeof(p)); +- p.fd = fd; +- p.events = POLLIN | POLLHUP; +- +- while (1) { +- n = poll(&p, 1, -1); +- if (n < 0) { +- throw std::runtime_error("Failed to poll RFKILL control device"); +- break; +- } ++waybar::util::Rfkill::~Rfkill() { ++ if (fd_ >= 0) { ++ close(fd_); ++ } ++} + +- if (n == 0) continue; ++bool waybar::util::Rfkill::on_event(Glib::IOCondition cond) { ++ if (cond & Glib::IO_IN) { ++ struct rfkill_event event; ++ ssize_t len; + +- len = read(fd, &event, sizeof(event)); ++ len = read(fd_, &event, sizeof(event)); + if (len < 0) { +- throw std::runtime_error("Reading of RFKILL events failed"); +- break; ++ if (errno == EAGAIN) { ++ return true; ++ } ++ spdlog::error("Reading of RFKILL events failed: {}", errno); ++ return false; + } + +- if (len != RFKILL_EVENT_SIZE_V1) { +- throw std::runtime_error("Wrong size of RFKILL event"); +- continue; ++ if (len < RFKILL_EVENT_SIZE_V1) { ++ spdlog::error("Wrong size of RFKILL event: {} < {}", len, RFKILL_EVENT_SIZE_V1); ++ return true; + } + +- if (event.type == rfkill_type_ && event.op == RFKILL_OP_CHANGE) { ++ if (event.type == rfkill_type_ && (event.op == RFKILL_OP_ADD || event.op == RFKILL_OP_CHANGE)) { + state_ = event.soft || event.hard; +- break; ++ on_update.emit(event); + } ++ return true; ++ } else { ++ spdlog::error("Failed to poll RFKILL control device"); ++ return false; + } +- +- close(fd); + } + + bool waybar::util::Rfkill::getState() const { return state_; } diff --git a/waybar.changes b/waybar.changes index c6f045a..e02666f 100644 --- a/waybar.changes +++ b/waybar.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Sun Mar 14 17:16:27 UTC 2021 - Matej Cepl + +- Add 1015-rfkill_code_refactoring.patch to avoid + gh#Alexays/Waybar#994 and boo#1183499. + ------------------------------------------------------------------- Mon Jan 4 10:35:11 UTC 2021 - Michael Vetter diff --git a/waybar.spec b/waybar.spec index ed6a74e..7b810e5 100644 --- a/waybar.spec +++ b/waybar.spec @@ -27,6 +27,8 @@ URL: https://github.com/Alexays/Waybar # to get the `date` dependency. and create own tarball #Source: https://github.com/Alexays/Waybar/archive/%{version}.tar.gz Source: %{version}.tar.xz +# PATCH-FIX-UPSTREAM 1015-rfkill_code_refactoring.patch gh#Alexays/Waybar#994 mcepl@suse.com +Patch0: 1015-rfkill_code_refactoring.patch BuildRequires: cmake BuildRequires: gcc-c++ BuildRequires: gtk-layer-shell-devel @@ -81,7 +83,7 @@ BuildArch: noarch This package provides the upstream look and feel for sway. %prep -%setup -q -n Waybar-%{version} +%autosetup -p1 -n Waybar-%{version} %build %meson -Dsndio=disabled