summaryrefslogtreecommitdiff
path: root/app-office/libreoffice/files/libreoffice-4.1.3.2-kde-recursiverepaint.patch
blob: 7067c019a33d778a603d7537ae4bc89ed1ae4dea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
Minor modification for libreoffice-4.1: in line 137, reset Q_EMIT to 
emit... dilfridge@gentoo.org

From 13a34f4c6307d1bd2443cbf3fbd83bfdd8cdbafb Mon Sep 17 00:00:00 2001
From: Jan-Marek Glogowski <glogow@fbihome.de>
Date: Fri, 15 Nov 2013 13:42:15 +0000
Subject: Rewrite Qt4 based nested yield mutex locking.

The Qt event loop may start a nested event loop, when checking for
clipboard and Drag'n'Drop events.

Previously this was handled by running this nested yield loop
inside the main glib loop using
  qApp->clipboard()->property( "useEventLoopWhenWaiting" );

But this results in nested paint events which crash LO:
  QWidget::repaint: Recursive repaint detected

To prevend yield mutex deadlocks, check for nested event loops
and always release the yield lock before starting the nested Yield
event loop.

This fixes fdo#69002.

Change-Id: I7e827abd3489783053ec7123372742a32555875d
Reviewed-on: https://gerrit.libreoffice.org/6685
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Reviewed-by: Thorsten Behrens <thb@documentfoundation.org>
Tested-by: Thorsten Behrens <thb@documentfoundation.org>
---
diff --git a/vcl/unx/kde4/KDE4FilePicker.cxx b/vcl/unx/kde4/KDE4FilePicker.cxx
index ee4a6e3..cb20be4 100644
--- a/vcl/unx/kde4/KDE4FilePicker.cxx
+++ b/vcl/unx/kde4/KDE4FilePicker.cxx
@@ -58,6 +58,8 @@
 
 #undef Region
 
+#include "generic/geninst.h"
+
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::ui::dialogs;
 using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
@@ -253,28 +255,16 @@ sal_Int16 SAL_CALL KDE4FilePicker::execute()
     _dialog->setFilter(_filter);
     _dialog->filterWidget()->setEditable(false);
 
-    // At this point, SolarMutex is held. Opening the KDE file dialog here
-    // can lead to QClipboard asking for clipboard contents. If LO core
-    // is the owner of the clipboard content, this will block for 5 seconds
-    // and timeout, since the clipboard thread will not be able to acquire
-    // SolarMutex and thus won't be able to respond. If the event loops
-    // are properly integrated and QClipboard can use a nested event loop
-    // (see the KDE VCL plug), then this won't happen, but otherwise
-    // simply release the SolarMutex here. The KDE file dialog does not
-    // call back to the core, so this should be safe (and if it does,
-    // SolarMutex will need to be re-acquired).
-    long mutexrelease = 0;
-    if( !qApp->clipboard()->property( "useEventLoopWhenWaiting" ).toBool())
-        mutexrelease = Application::ReleaseSolarMutex();
-    //block and wait for user input
+    // We're entering a nested loop.
+    // Release the yield mutex to prevent deadlocks.
     int result = _dialog->exec();
+
     // HACK: KFileDialog uses KConfig("kdeglobals") for saving some settings
     // (such as the auto-extension flag), but that doesn't update KGlobal::config()
     // (which is probably a KDE bug), so force reading the new configuration,
     // otherwise the next opening of the dialog would use the old settings.
     KGlobal::config()->reparseConfiguration();
-    if( !qApp->clipboard()->property( "useEventLoopWhenWaiting" ).toBool())
-        Application::AcquireSolarMutex( mutexrelease );
+
     if( result == KFileDialog::Accepted)
         return ExecutableDialogResults::OK;
 
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index 8e0eb67..67d7a4d 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -225,9 +225,6 @@ void KDEXLib::setupEventLoop()
         eventLoopType = GlibEventLoop;
         old_gpoll = g_main_context_get_poll_func( NULL );
         g_main_context_set_poll_func( NULL, gpoll_wrapper );
-        // set QClipboard to use event loop, otherwise the main thread will hold
-        // SolarMutex locked, which will prevent the clipboard thread from answering
-        m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true );
         return;
     }
 #endif
@@ -244,9 +241,6 @@ void KDEXLib::setupEventLoop()
         eventLoopType = QtUnixEventLoop;
         QInternal::callFunction( QInternal::GetUnixSelectFunction, reinterpret_cast< void** >( &qt_select ));
         QInternal::callFunction( QInternal::SetUnixSelectFunction, reinterpret_cast< void** >( lo_select ));
-        // set QClipboard to use event loop, otherwise the main thread will hold
-        // SolarMutex locked, which will prevent the clipboard thread from answering
-        m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true );
         return;
     }
 #endif
@@ -300,6 +294,9 @@ void KDEXLib::socketNotifierActivated( int fd )
 
 void KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
 {
+    // Nested yield loop counter.
+    static int loop_depth = 0;
+
     if( eventLoopType == LibreOfficeEventLoop )
     {
         if( qApp->thread() == QThread::currentThread())
@@ -310,13 +307,24 @@ void KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
         }
         return SalXLib::Yield( bWait, bHandleAllCurrentEvents );
     }
+
     // if we are the main thread (which is where the event processing is done),
     // good, just do it
-    if( qApp->thread() == QThread::currentThread())
+    if( qApp->thread() == QThread::currentThread()) {
+        // Release the yield lock before entering a nested loop.
+        if (loop_depth > 0)
+            SalYieldMutexReleaser aReleaser;
+        loop_depth++;
         processYield( bWait, bHandleAllCurrentEvents );
-    else
-    { // if this deadlocks, event processing needs to go into a separate thread
-      // or some other solution needs to be found
+        loop_depth--;
+    }
+    else {
+        // we were called from another thread;
+        // release the yield lock to prevent deadlock.
+        SalYieldMutexReleaser aReleaser;
+
+        // if this deadlocks, event processing needs to go into a separate
+        // thread or some other solution needs to be found
         emit processYieldSignal( bWait, bHandleAllCurrentEvents );
     }
 }
--
cgit v0.9.0.2-2-gbebe