fix(wireplumber): guard async callbacks by connection generation; wire scroll once
Addresses review on #5168: - Generational aliasing (blocking): setupConnection()/onReconnectTimeout() rebuild wp_core_/om_/pending_plugins_ in place on the same self, but the async load/activate callbacks carried no generation, and isModuleAlive() only proves self still exists. If PipeWire dropped again while a previous connection's async chain was still in flight, a stale completion would run against the rebuilt connection (a stray --pending_plugins_, an out-of-order install_object_manager), re-creating #2882's stale/blank state. Each async call now carries an AsyncCall{self, generation}; connection_generation_ is bumped in setupConnection(), and every callback drops out when its generation no longer matches (checked after isModuleAlive short-circuits). - Duplicate scroll handlers: onMixerApiLoaded re-runs on every reconnect and connected a new scroll handler each time (dead but accumulating). Moved the one-time wiring to the constructor; handleScroll no-ops while mixer_api_ is null, so wiring it before the first connect is safe.
This commit is contained in:
@@ -29,10 +29,9 @@ class Wireplumber : public ALabel {
|
||||
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
|
||||
static void updateSourceVolume(waybar::modules::Wireplumber* self, uint32_t id);
|
||||
static void updateSourceName(waybar::modules::Wireplumber* self, uint32_t id); // NEW
|
||||
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
|
||||
waybar::modules::Wireplumber* self);
|
||||
static void onMixerApiLoaded(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||
static void onPluginActivated(WpObject* p, GAsyncResult* res, gpointer data);
|
||||
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res, gpointer data);
|
||||
static void onMixerApiLoaded(WpObject* p, GAsyncResult* res, gpointer data);
|
||||
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
|
||||
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
|
||||
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
|
||||
@@ -57,6 +56,10 @@ class Wireplumber : public ALabel {
|
||||
WpPlugin* def_nodes_api_;
|
||||
gchar* default_node_name_;
|
||||
uint32_t pending_plugins_;
|
||||
// Bumped on every (re)connection. The async load/activate callbacks capture the generation they
|
||||
// were scheduled under (via their user_data) and no-op if it no longer matches, so a completion
|
||||
// from a connection that was already torn down cannot corrupt the new generation's state (#2882).
|
||||
uint32_t connection_generation_{0};
|
||||
bool muted_;
|
||||
double volume_;
|
||||
double min_step_;
|
||||
|
||||
Reference in New Issue
Block a user