From 6517d72d1349c974b61217e81b5f1e17e5a93430 Mon Sep 17 00:00:00 2001
From: Pierre Lamot <pierre@videolabs.io>
Date: Thu, 6 Jan 2022 18:21:42 +0100
Subject: [PATCH] qt: don't handle object destruction event after ML task is
 done or canceled

The MediaLib object can perform ML requests itself, this would register an event
called on object destruction, that would callback on itself but the MediaLib
would be in an invalid state (partially destroyed).

Anyway we shouldn't handle object destruction events after ML task is done or
canceled

fix: #26448
---
 modules/gui/qt/medialibrary/medialib.cpp | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/modules/gui/qt/medialibrary/medialib.cpp b/modules/gui/qt/medialibrary/medialib.cpp
index ef4cbdf52621..ad51ecea8e6e 100644
--- a/modules/gui/qt/medialibrary/medialib.cpp
+++ b/modules/gui/qt/medialibrary/medialib.cpp
@@ -42,6 +42,8 @@ MediaLib::MediaLib(qt_intf_t *_intf, QObject *_parent)
 
 MediaLib::~MediaLib()
 {
+    assert(m_objectTasks.empty());
+    assert(m_runningTasks.empty());
 }
 
 void MediaLib::destroy()
@@ -50,6 +52,7 @@ void MediaLib::destroy()
     //try to cancel as many tasks as possible
     for (auto taskIt = m_objectTasks.begin(); taskIt != m_objectTasks.end(); /**/)
     {
+        const QObject* object = taskIt.key();
         quint64 key = taskIt.value();
         auto task = m_runningTasks.value(key, nullptr);
         if (m_mlThreadPool.tryTake(task))
@@ -57,6 +60,8 @@ void MediaLib::destroy()
             delete task;
             m_runningTasks.remove(key);
             taskIt = m_objectTasks.erase(taskIt);
+            if (m_objectTasks.count(object) == 0)
+                disconnect(object, &QObject::destroyed, this, &MediaLib::runOnMLThreadTargetDestroyed);
         }
         else
             ++taskIt;
@@ -468,6 +473,8 @@ void MediaLib::cancelMLTask(const QObject* object, quint64 taskId)
         delete task;
     m_runningTasks.remove(taskId);
     m_objectTasks.remove(object, taskId);
+    if (m_objectTasks.count(object) == 0)
+        disconnect(object, &QObject::destroyed, this, &MediaLib::runOnMLThreadTargetDestroyed);
 }
 
 void MediaLib::runOnMLThreadDone(RunOnMLThreadBaseRunner* runner, quint64 target, const QObject* object, int status)
@@ -478,6 +485,8 @@ void MediaLib::runOnMLThreadDone(RunOnMLThreadBaseRunner* runner, quint64 target
         {
             m_runningTasks.remove(target);
             m_objectTasks.remove(object, target);
+            if (m_objectTasks.count(object) == 0)
+                disconnect(object, &QObject::destroyed, this, &MediaLib::runOnMLThreadTargetDestroyed);
         }
         if (m_runningTasks.empty())
             deleteLater();
@@ -488,6 +497,8 @@ void MediaLib::runOnMLThreadDone(RunOnMLThreadBaseRunner* runner, quint64 target
             runner->runUICallback();
         m_runningTasks.remove(target);
         m_objectTasks.remove(object, target);
+        if (m_objectTasks.count(object) == 0)
+            disconnect(object, &QObject::destroyed, this, &MediaLib::runOnMLThreadTargetDestroyed);
     }
     runner->deleteLater();
 }
@@ -506,5 +517,6 @@ void MediaLib::runOnMLThreadTargetDestroyed(QObject * object)
             m_runningTasks.remove(taskId);
         }
         m_objectTasks.remove(object);
+        //no need to disconnect QObject::destroyed, as object is currently being destroyed
     }
 }
-- 
GitLab