Kaydet (Commit) 07157e64 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

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/22291Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarStephan Bergmann <sbergman@redhat.com>
üst 76352133
......@@ -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() {}
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment