forked from quickshell/quickshell
		
	services/pipewire: destroy qml ifaces early to avoid user callbacks
Consumers of defaultAudio*Changed signals can run code between safeDestroy being called and PwObjectIface destruction due to signal connection order. This change destroys ifaces earlier so they are nulled by the time a changed signal is fired from destruction, preventing access between ~PwNode() and ~QObject() completion. Fixes #116 #122 #124
This commit is contained in:
		
							parent
							
								
									201c559dcd
								
							
						
					
					
						commit
						91dcb41d22
					
				
					 2 changed files with 14 additions and 1 deletions
				
			
		| 
						 | 
					@ -18,6 +18,16 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace qs::service::pipewire {
 | 
					namespace qs::service::pipewire {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PwObjectIface::PwObjectIface(PwBindableObject* object): QObject(object), object(object) {
 | 
				
			||||||
 | 
						// We want to destroy the interface before QObject::destroyed is fired, as handlers
 | 
				
			||||||
 | 
						// connected before PwObjectIface will run first and emit signals that hit user code,
 | 
				
			||||||
 | 
						// which can then try to reference the iface again after ~PwNode() has been called but
 | 
				
			||||||
 | 
						// before ~QObject() has finished.
 | 
				
			||||||
 | 
						QObject::connect(object, &PwBindableObject::destroying, this, &PwObjectIface::onObjectDestroying);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PwObjectIface::onObjectDestroying() { delete this; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PwObjectIface::ref() {
 | 
					void PwObjectIface::ref() {
 | 
				
			||||||
	this->refcount++;
 | 
						this->refcount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ class PwObjectIface
 | 
				
			||||||
	Q_OBJECT;
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	explicit PwObjectIface(PwBindableObject* object): QObject(object), object(object) {};
 | 
						explicit PwObjectIface(PwBindableObject* object);
 | 
				
			||||||
	// destructor should ONLY be called by the pw object destructor, making an unref unnecessary
 | 
						// destructor should ONLY be called by the pw object destructor, making an unref unnecessary
 | 
				
			||||||
	~PwObjectIface() override = default;
 | 
						~PwObjectIface() override = default;
 | 
				
			||||||
	Q_DISABLE_COPY_MOVE(PwObjectIface);
 | 
						Q_DISABLE_COPY_MOVE(PwObjectIface);
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,9 @@ public:
 | 
				
			||||||
	void ref() override;
 | 
						void ref() override;
 | 
				
			||||||
	void unref() override;
 | 
						void unref() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
						void onObjectDestroying();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	quint32 refcount = 0;
 | 
						quint32 refcount = 0;
 | 
				
			||||||
	PwBindableObject* object;
 | 
						PwBindableObject* object;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue