avmedia/source/gstreamer/gstplayer.cxx |   27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

New commits:
commit 04311ac7bf89b2496a951b377c8d7f6be5b8c188
Author:     Stephan Bergmann <[email protected]>
AuthorDate: Thu Nov 27 10:17:18 2025 +0100
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Thu Nov 27 13:57:07 2025 +0100

    Fix race between MissingPluginInstallerThread launch() and join()
    
    CppunitTest_slideshow_engine occasionally failed at least on
    <https://ci.libreoffice.org/job/gerrit_linux_gcc_release/>, with a
    MissingPluginInstallerThread still executing during exit.  What happened was
    that the join() in MissingPluginInstaller::detach was executed before the
    launch() in the MissingPluginInstaller launchUi link was called.  So that 
call
    to join() did nothing (cf. the documentation of osl_joinWithThread in
    include/osl/thread.h: "Returns immediately if Thread is NULL.") and then the
    call to create() started executing the thread during exit.
    
    Change-Id: I5141eba64e6631cbf41026af4bbee4fc0a285a4f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194686
    Reviewed-by: Noel Grandin <[email protected]>
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>
    Code-Style: Stephan Bergmann <[email protected]>

diff --git a/avmedia/source/gstreamer/gstplayer.cxx 
b/avmedia/source/gstreamer/gstplayer.cxx
index 602435db5f83..d63b8e809bf7 100644
--- a/avmedia/source/gstreamer/gstplayer.cxx
+++ b/avmedia/source/gstreamer/gstplayer.cxx
@@ -70,8 +70,29 @@ class MissingPluginInstallerThread: public salhelper::Thread 
{
 public:
     MissingPluginInstallerThread(): Thread("MissingPluginInstaller") {}
 
+    void launchIfNotJoined() {
+        std::scoped_lock g(mutex_);
+        if (!joined_) {
+            launch();
+        }
+    }
+
+    void joinIfCreated() {
+        {
+            std::scoped_lock g(mutex_);
+            joined_ = true;
+        }
+        join(); // if not yet created, join() does nothing
+    }
+
 private:
+    using salhelper::Thread::launch;
+    using salhelper::Thread::join;
+
     void execute() override;
+
+    std::mutex mutex_;
+    bool joined_ = false;
 };
 
 
@@ -156,7 +177,7 @@ void MissingPluginInstaller::report(
         launch = currentThread_;
     }
     if (join.is()) {
-        join->join();
+        join->joinIfCreated();
     }
     launch->acquire();
     Application::PostUserEvent(
@@ -209,7 +230,7 @@ void MissingPluginInstaller::detach(Player const * source) {
     }
     if (join.is()) {
         // missing cancellability of gst_install_plugins_sync
-        join->join();
+        join->joinIfCreated();
     }
 }
 
@@ -238,7 +259,7 @@ IMPL_STATIC_LINK(MissingPluginInstaller, launchUi, void *, 
p, void)
         // loop), and hopefully fine to call gst_is_missing_plugin_message and
         // gst_missing_plugin_message_get_installer_detail before calling
         // gst_pb_utils_init
-    ref->launch();
+    ref->launchIfNotJoined();
 }
 
 

Reply via email to