Kaydet (Commit) 78f05c0a authored tarafından Michael Stahl's avatar Michael Stahl

toolkit: avoid deadlock in UnoControl::setDesignMode()

Avoid deadlock by disposing the accesibility context without the Mutex
locked, since it will eventually try to acquire the SolarMutex...

Thread 1 in UnoControl::getPosSize()
calling from sdr::contact::ControlHolder::getPosSize()

Thread 2 calling from UnoControl::setDesignMode()
trying to get SolarMutex in VCLXWindow::disposing()

Change-Id: I7d0ffe4fa0f8cd0c48e9b9b5e923ce229f97ca57
üst cf88ebc1
...@@ -124,7 +124,8 @@ protected: ...@@ -124,7 +124,8 @@ protected:
void ImplLockPropertyChangeNotification( const OUString& rPropertyName, bool bLock ); void ImplLockPropertyChangeNotification( const OUString& rPropertyName, bool bLock );
void ImplLockPropertyChangeNotifications( const ::com::sun::star::uno::Sequence< OUString >& rPropertyNames, bool bLock ); void ImplLockPropertyChangeNotifications( const ::com::sun::star::uno::Sequence< OUString >& rPropertyNames, bool bLock );
void disposeAccessibleContext(); void DisposeAccessibleContext(::com::sun::star::uno::Reference<
::com::sun::star::lang::XComponent> const& xContext);
inline void setPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _xPeer) inline void setPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >& _xPeer)
{ {
......
...@@ -787,7 +787,9 @@ void SAL_CALL FmXGridControl::setDesignMode(sal_Bool bOn) throw( RuntimeExceptio ...@@ -787,7 +787,9 @@ void SAL_CALL FmXGridControl::setDesignMode(sal_Bool bOn) throw( RuntimeExceptio
// dispose our current AccessibleContext, if we have one // dispose our current AccessibleContext, if we have one
// (changing the design mode implies having a new implementation for this context, // (changing the design mode implies having a new implementation for this context,
// so the old one must be declared DEFUNC) // so the old one must be declared DEFUNC)
disposeAccessibleContext(); DisposeAccessibleContext(
Reference<XComponent>(maAccessibleContext, UNO_QUERY));
maAccessibleContext.clear();
// prepare firing an event // prepare firing an event
aModeChangeEvent.Source = *this; aModeChangeEvent.Source = *this;
......
...@@ -333,12 +333,11 @@ void UnoControl::updateFromModel() ...@@ -333,12 +333,11 @@ void UnoControl::updateFromModel()
// XTypeProvider // XTypeProvider
IMPL_IMPLEMENTATION_ID( UnoControl ) IMPL_IMPLEMENTATION_ID( UnoControl )
void UnoControl::disposeAccessibleContext() void
UnoControl::DisposeAccessibleContext(Reference<XComponent> const& xContextComp)
{ {
Reference< XComponent > xContextComp( maAccessibleContext.get(), UNO_QUERY ); if (xContextComp.is())
if ( xContextComp.is() )
{ {
maAccessibleContext = NULL;
try try
{ {
xContextComp->removeEventListener( this ); xContextComp->removeEventListener( this );
...@@ -354,6 +353,7 @@ void UnoControl::disposeAccessibleContext() ...@@ -354,6 +353,7 @@ void UnoControl::disposeAccessibleContext()
void UnoControl::dispose( ) throw(RuntimeException) void UnoControl::dispose( ) throw(RuntimeException)
{ {
Reference< XWindowPeer > xPeer; Reference< XWindowPeer > xPeer;
Reference<XComponent> xAccessibleComp;
{ {
::osl::MutexGuard aGuard( GetMutex() ); ::osl::MutexGuard aGuard( GetMutex() );
if( mbDisposePeer ) if( mbDisposePeer )
...@@ -361,14 +361,16 @@ void UnoControl::dispose( ) throw(RuntimeException) ...@@ -361,14 +361,16 @@ void UnoControl::dispose( ) throw(RuntimeException)
xPeer = mxPeer; xPeer = mxPeer;
} }
setPeer( NULL ); setPeer( NULL );
xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
maAccessibleContext.clear();
} }
if( xPeer.is() ) if( xPeer.is() )
{ {
xPeer->dispose(); xPeer->dispose();
} }
// dispose and release our AccessibleContext // dispose our AccessibleContext - without Mutex locked
disposeAccessibleContext(); DisposeAccessibleContext(xAccessibleComp);
EventObject aDisposeEvent; EventObject aDisposeEvent;
aDisposeEvent.Source = static_cast< XAggregation* >( this ); aDisposeEvent.Source = static_cast< XAggregation* >( this );
...@@ -1382,6 +1384,7 @@ void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException) ...@@ -1382,6 +1384,7 @@ void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
ModeChangeEvent aModeChangeEvent; ModeChangeEvent aModeChangeEvent;
Reference< XWindow > xWindow; Reference< XWindow > xWindow;
Reference<XComponent> xAccessibleComp;
{ {
::osl::MutexGuard aGuard( GetMutex() ); ::osl::MutexGuard aGuard( GetMutex() );
if ( bOn == mbDesignMode ) if ( bOn == mbDesignMode )
...@@ -1390,15 +1393,19 @@ void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException) ...@@ -1390,15 +1393,19 @@ void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
// remember this // remember this
mbDesignMode = bOn; mbDesignMode = bOn;
xWindow = xWindow.query( getPeer() ); xWindow = xWindow.query( getPeer() );
// dispose our current AccessibleContext, if we have one
// (changing the design mode implies having a new implementation for this context, xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
// so the old one must be declared DEFUNC) maAccessibleContext.clear();
disposeAccessibleContext();
aModeChangeEvent.Source = *this; aModeChangeEvent.Source = *this;
aModeChangeEvent.NewMode = mbDesignMode ? OUString("design") : OUString("alive" ); aModeChangeEvent.NewMode = mbDesignMode ? OUString("design") : OUString("alive" );
} }
// dispose current AccessibleContext, if we have one - without Mutex lock
// (changing the design mode implies having a new implementation for this context,
// so the old one must be declared DEFUNC)
DisposeAccessibleContext(xAccessibleComp);
// ajust the visibility of our window // ajust the visibility of our window
if ( xWindow.is() ) if ( xWindow.is() )
xWindow->setVisible( !bOn ); xWindow->setVisible( !bOn );
......
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