[Libreoffice-commits] core.git: vcl/inc vcl/unx

Stephan Bergmann sbergman at redhat.com
Thu Feb 11 17:33:09 UTC 2016


 vcl/inc/unx/gtk/gtkinst.hxx |    2 +-
 vcl/unx/gtk/gtkinst.cxx     |   23 +++++++++--------------
 2 files changed, 10 insertions(+), 15 deletions(-)

New commits:
commit 07157e644fa9666850767ff6bd54c1511167a0a2
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Thu Feb 11 17:34:35 2016 +0100

    Keep track of ThreadsEnter/Leave acquire counts per thread
    
    Appears that gtk_clipboard_wait_for_targets (called from
    GtkClipboardTransferable::getTransferDataFlavorsAsVector,
    vcl/unx/gtk3/gtk3gtkinst.cxx) internally calls gdk_threads_leave/enter, so if
    two threads concurrently try to call into getTransferDataFlavorsAsVector, each
    with the SolarMutex recursively acquired a different number of times, the
    GtkYieldMutex::ThreadsLeave/Enter calls can pair up so that the threads' acquire
    counts get swapped.  Then eventually causing one thread to prematurely get the
    SolarMutex unlocked.
    
    This was fairly well reproducible when calling an --enable-dbgutil's soffice
    with an .oxt file on the command line, causing both the Extension Manager dialog
    and an empty Writer document to open simultaneously (which apparently both run
    into the above getTransferDataFlavorsAsVector), and then running into some
    DBG_TESTSOLARMUTEX assert firing when the SolarMutex had been unlocked
    prematurely.
    
    According to <http://en.cppreference.com/w/cpp/compiler_support>, support for
    thread_local is available partially since GCC 4.4 and fully only since GCC 4.8,
    so hope the partial support in GCC 4.7 (our current baseline) is good enough for
    what is used here.
    
    Change-Id: I9fad318078be5f31111a7cbd15d0e1349e7ddd3e
    Reviewed-on: https://gerrit.libreoffice.org/22291
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index 3122956..6f1f999 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -42,7 +42,7 @@ class GtkPrintWrapper;
 class GenPspGraphics;
 class GtkYieldMutex : public SalYieldMutex
 {
-    std::list<sal_uLong> aYieldStack;
+    thread_local static sal_uIntPtr yieldCount;
 
 public:
          GtkYieldMutex() {}
diff --git a/vcl/unx/gtk/gtkinst.cxx b/vcl/unx/gtk/gtkinst.cxx
index 0b3ef7b..a1b7522 100644
--- a/vcl/unx/gtk/gtkinst.cxx
+++ b/vcl/unx/gtk/gtkinst.cxx
@@ -288,29 +288,24 @@ SalPrinter* GtkInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
  * for each pair, so we can accurately restore
  * it later.
  */
+thread_local sal_uIntPtr GtkYieldMutex::yieldCount;
+
 void GtkYieldMutex::ThreadsEnter()
 {
     acquire();
-    if( !aYieldStack.empty() )
-    { /* Previously called ThreadsLeave() */
-        sal_uLong nCount = aYieldStack.front();
-        aYieldStack.pop_front();
-        while( nCount-- > 1 )
-            acquire();
+    for (; yieldCount != 0; --yieldCount) {
+        acquire();
     }
 }
 
 void GtkYieldMutex::ThreadsLeave()
 {
-    aYieldStack.push_front( mnCount );
-
-    SAL_WARN_IF(
-        mnThreadId && mnThreadId != osl::Thread::getCurrentIdentifier(),
-        "vcl.gtk", "other thread " << mnThreadId << " owns the mutex");
-
-    while( mnCount > 1 )
+    assert(mnCount != 0);
+    assert(yieldCount == 0);
+    yieldCount = mnCount - 1;
+    for (sal_uIntPtr i = 0; i != yieldCount + 1; ++i) {
         release();
-    release();
+    }
 }
 
 SalVirtualDevice* GtkInstance::CreateVirtualDevice( SalGraphics *pG,


More information about the Libreoffice-commits mailing list