The privacy module registers timeout callbacks in the GLib main context.
The GeoClue callback uses sigc::mem_fun() with the Privacy object, but the
connection remains active when the module is destroyed during a bar reload.
If the timeout runs after destruction, it dereferences the freed Privacy
object and crashes Waybar:
#0 waybar::modules::privacy::Privacy::locationTimeout(bool)
#4 g_main_context_iteration()
#5 g_application_run()
Disconnect the GeoClue and visibility timeout connections in the Privacy
destructor so no callback can run after the module is gone.
The unpatched binary crashed after four SIGUSR2 reloads at 1.5-second
intervals. The patched binary survived ten reloads.
Fixes: eeb7bc702e ("Added GeoClue2 privacy item")
Assisted-by: Claude Opus + Cursor
51 lines
1.6 KiB
C++
51 lines
1.6 KiB
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <string>
|
|
|
|
#include "gtkmm/box.h"
|
|
#include "modules/privacy/privacy_item.hpp"
|
|
#include "util/geoclue_backend.hpp"
|
|
#include "util/pipewire/pipewire_backend.hpp"
|
|
#include "util/pipewire/privacy_node_info.hpp"
|
|
|
|
using waybar::util::PipewireBackend::PrivacyNodeType;
|
|
using waybar::util::PipewireBackend::PWPrivacyNodeInfo;
|
|
|
|
namespace waybar::modules::privacy {
|
|
|
|
class Privacy : public AModule {
|
|
public:
|
|
Privacy(const std::string&, const Json::Value&, Gtk::Orientation, const std::string& pos);
|
|
~Privacy() override;
|
|
auto update() -> void override;
|
|
|
|
private:
|
|
std::list<PWPrivacyNodeInfo*> nodes_screenshare; // Screen is being shared
|
|
std::list<PWPrivacyNodeInfo*> nodes_audio_in; // Application is using the microphone
|
|
std::list<PWPrivacyNodeInfo*> nodes_audio_out; // Application is outputting audio
|
|
std::atomic<bool> location_in_use; // GeoClue is being used
|
|
|
|
std::mutex mutex_;
|
|
sigc::connection visibility_conn;
|
|
sigc::connection geoclue_timeout_conn;
|
|
|
|
// Config
|
|
Gtk::Box box_;
|
|
std::vector<PrivacyItem*> modules_;
|
|
uint iconSpacing = 4;
|
|
uint iconSize = 20;
|
|
uint transition_duration = 250;
|
|
std::set<std::pair<PrivacyNodeType, std::string>> ignore;
|
|
bool ignore_monitor = true;
|
|
|
|
std::shared_ptr<util::PipewireBackend::PipewireBackend> pw_backend = nullptr;
|
|
std::shared_ptr<util::GeoClueBackend::GeoClueBackend> geoclue_backend = nullptr;
|
|
|
|
void onPWPrivacyNodesChanged();
|
|
bool locationTimeout(bool in_use);
|
|
void onGeoCluePrivacyNodesChanged();
|
|
};
|
|
|
|
} // namespace waybar::modules::privacy
|