diff --git a/ext/libclementine-common/core/closure.cpp b/ext/libclementine-common/core/closure.cpp index ff0ed120f..aa5ea98e0 100644 --- a/ext/libclementine-common/core/closure.cpp +++ b/ext/libclementine-common/core/closure.cpp @@ -37,8 +37,15 @@ ObjectHelper* ClosureBase::helper() const { return helper_; } ObjectHelper::ObjectHelper(QObject* sender, const char* signal, ClosureBase* closure) : closure_(closure) { - connect(sender, signal, SLOT(Invoked())); - connect(sender, SIGNAL(destroyed()), SLOT(deleteLater())); + connection_ = connect(sender, signal, SLOT(Invoked())); + connect(sender, SIGNAL(destroyed()), SLOT(TearDown())); +} + +void ObjectHelper::TearDown() { + // For the case that the receiver has been destroyed, disconnect the signal + // so that Invoke isn't called. + disconnect(connection_); + deleteLater(); } void ObjectHelper::Invoked() { diff --git a/ext/libclementine-common/core/closure.h b/ext/libclementine-common/core/closure.h index 1d44cd212..fafc69abc 100644 --- a/ext/libclementine-common/core/closure.h +++ b/ext/libclementine-common/core/closure.h @@ -58,10 +58,14 @@ class ObjectHelper : public QObject { public: ObjectHelper(QObject* parent, const char* signal, ClosureBase* closure); + public slots: + void TearDown(); + private slots: void Invoked(); private: + QMetaObject::Connection connection_; std::unique_ptr closure_; Q_DISABLE_COPY(ObjectHelper) }; @@ -97,8 +101,11 @@ class Closure : public ClosureBase { const int index = meta_receiver->indexOfSlot(normalised_slot.constData()); Q_ASSERT(index != -1); slot_ = meta_receiver->method(index); - QObject::connect(receiver_, SIGNAL(destroyed()), helper_, - SLOT(deleteLater())); + // Use a direct connection to insure that this is called immediately when + // the sender is destroyed. This will run on the signal thread, so TearDown + // must be thread safe. + QObject::connect(receiver_, SIGNAL(destroyed()), helper_, SLOT(TearDown()), + Qt::DirectConnection); } virtual void Invoke() { function_(); }