summaryrefslogtreecommitdiff
path: root/dbaccess
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2016-07-26 23:42:36 +0200
committerMichael Stahl <mstahl@redhat.com>2016-07-29 10:05:47 +0000
commita2095b151409f0fb57aa8feaa4c6282f84040245 (patch)
tree08d70dc7853bb2eafa69bf3cb8c9eceb7df2e5fd /dbaccess
parentb3b7669e7fb74b04d925f21a7f0b048434eeffa3 (diff)
comphelper,vcl: let DeInitVCL() join some AsyncEventNotifier threads
comphelper::AsyncEventNotifier is an amazing class that dispatches events in separate threads, no doubt implemented during times of exuberant optimism about the tractability of shared-state multi-threading. Unfortunately the authors forgot to think about how all those awesome threads will be joined, so if they are somehow blocked, then it may well happen that the events are dispatched when the main thread is already in DeInitVCL, and the objects required for the dispatching already smell somewhat funny. This happens quite reproducibly when changing dbaccess' ModelMethodGuard to lock the SolarMutex too, then CppunitTest_dbaccess_RowSetClones crashes in DeInitVCL() because one AsyncEventNotifier thread was blocked until then by SolarMutexGuard, and this test never Yields once its document is loaded. Try to fix this by joining the "DocumentEventNotifier" threads from DeInitVCL() itself. Since there's no rtl::WeakReference to go with rtl::Reference, refactor the AsyncEventNotifier and create a new AsyncEventNotifierAutoJoin that has to be used with std::shared_ptr and std::weak_ptr. Change-Id: I50a0749795acb04b0776e543f7125767b697ea35 Reviewed-on: https://gerrit.libreoffice.org/27581 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Michael Stahl <mstahl@redhat.com>
Diffstat (limited to 'dbaccess')
-rw-r--r--dbaccess/source/core/dataaccess/documenteventnotifier.cxx24
1 files changed, 15 insertions, 9 deletions
diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.cxx b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx
index 0f4d3f21130c..aca027e159d9 100644
--- a/dbaccess/source/core/dataaccess/documenteventnotifier.cxx
+++ b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx
@@ -50,7 +50,7 @@ namespace dbaccess
::osl::Mutex& m_rMutex;
bool m_bInitialized;
bool m_bDisposed;
- ::rtl::Reference< ::comphelper::AsyncEventNotifier > m_pEventBroadcaster;
+ ::std::shared_ptr<::comphelper::AsyncEventNotifierAutoJoin> m_pEventBroadcaster;
::comphelper::OInterfaceContainerHelper2 m_aLegacyEventListeners;
::comphelper::OInterfaceContainerHelper2 m_aDocumentEventListeners;
@@ -137,7 +137,7 @@ namespace dbaccess
// SYNCHRONIZED ->
// cancel any pending asynchronous events
::osl::ResettableMutexGuard aGuard( m_rMutex );
- if ( m_pEventBroadcaster.is() )
+ if (m_pEventBroadcaster)
{
m_pEventBroadcaster->removeEventsForProcessor( this );
m_pEventBroadcaster->terminate();
@@ -147,7 +147,9 @@ namespace dbaccess
// in atexit handlers; simply calling join here leads to
// deadlock, as this thread holds the solar mutex while the
// other thread is typically blocked waiting for the solar mutex
- m_pEventBroadcaster.clear();
+ // For now, use newAutoJoinAsyncEventNotifier which is
+ // better than nothing.
+ m_pEventBroadcaster.reset();
}
lang::EventObject aEvent( m_rDocument );
@@ -169,9 +171,11 @@ namespace dbaccess
throw DoubleInitializationException();
m_bInitialized = true;
- if ( m_pEventBroadcaster.is() )
+ if (m_pEventBroadcaster)
+ {
// there are already pending asynchronous events
- m_pEventBroadcaster->launch();
+ ::comphelper::AsyncEventNotifierAutoJoin::launch(m_pEventBroadcaster);
+ }
}
void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent )
@@ -199,14 +203,16 @@ namespace dbaccess
void DocumentEventNotifier_Impl::impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent )
{
- if ( !m_pEventBroadcaster.is() )
+ if (!m_pEventBroadcaster)
{
- m_pEventBroadcaster.set(
- new ::comphelper::AsyncEventNotifier("DocumentEventNotifier"));
+ m_pEventBroadcaster = ::comphelper::AsyncEventNotifierAutoJoin
+ ::newAsyncEventNotifierAutoJoin("DocumentEventNotifier");
if ( m_bInitialized )
+ {
// start processing the events if and only if we (our document, respectively) are
// already initialized
- m_pEventBroadcaster->launch();
+ ::comphelper::AsyncEventNotifierAutoJoin::launch(m_pEventBroadcaster);
+ }
}
m_pEventBroadcaster->addEvent( new DocumentEventHolder( _rEvent ), this );
}