diff options
author | Caolán McNamara <caolanm@redhat.com> | 2013-11-20 16:17:54 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2013-11-20 16:20:21 +0000 |
commit | 32a621027f1a234a85b3659b93752a9263d8e860 (patch) | |
tree | f757b2a066b2ab8bf87f3fdf3140a1a95bef45bb /sfx2 | |
parent | 12b577cdab73ac5ae1a97fd2739ed4bfb652ea44 (diff) |
Resolves: fdo#70703 guard against FlushImpl inside FlushImpl
where the inner one deletes Shells that the outer one is still
processing. Push the candidates onto a stack and let inner
FlushImpl modify them to inform outer FlushImpl's that an entry
has been deleted
Change-Id: I1db8546d53e24cc96c72f2cd5cbec57b6cecaff5
Diffstat (limited to 'sfx2')
-rw-r--r-- | sfx2/source/control/dispatch.cxx | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx index 923a6152859a..934a6cbb6699 100644 --- a/sfx2/source/control/dispatch.cxx +++ b/sfx2/source/control/dispatch.cxx @@ -69,31 +69,6 @@ DBG_NAME(SfxDispatcherFillState) typedef std::vector<SfxRequest*> SfxRequestPtrArray; -struct SfxToDo_Impl -{ - SfxShell* pCluster; - bool bPush; - bool bDelete; - bool bUntil; - - SfxToDo_Impl() - : pCluster(0) - , bPush(false) - , bDelete(false) - , bUntil(false) - {} - SfxToDo_Impl( bool bOpPush, bool bOpDelete, bool bOpUntil, SfxShell& rCluster ) - : pCluster(&rCluster) - , bPush(bOpPush) - , bDelete(bOpDelete) - , bUntil(bOpUntil) - {} - ~SfxToDo_Impl(){} - - bool operator==( const SfxToDo_Impl& rWith ) const - { return pCluster==rWith.pCluster && bPush==rWith.bPush; } -}; - struct SfxObjectBars_Impl { sal_uInt32 nResId; // Resource - and ConfigId of the Toolbox @@ -1627,22 +1602,49 @@ void SfxDispatcher::FlushImpl() bFlushed = sal_True; OSL_TRACE("Successfully flushed dispatcher!"); + //fdo#70703 FlushImpl may call back into itself so use aToDoCopyStack to talk + //to outer levels of ourself. If DoActivate_Impl/DoDeactivate_Impl deletes + //an entry, then they will walk back up aToDoCopyStack and set outer + //levels's entries to bDeleted + aToDoCopyStack.push_back(aToDoCopy); + std::deque<SfxToDo_Impl>& rToDoCopy = aToDoCopyStack.back(); // Activate the Shells and possible delete them in the 2nd round - for(std::deque<SfxToDo_Impl>::reverse_iterator i = aToDoCopy.rbegin(); i != aToDoCopy.rend(); ++i) - { - if(i->bPush) - { - if ( pImp->bActive ) - i->pCluster->DoActivate_Impl(pImp->pFrame, sal_True); - } - else if ( pImp->bActive ) - i->pCluster->DoDeactivate_Impl(pImp->pFrame, sal_True); + for(std::deque<SfxToDo_Impl>::reverse_iterator i = rToDoCopy.rbegin(); i != rToDoCopy.rend(); ++i) + { + if (i->bDeleted) + continue; + if (!pImp->bActive) + continue; + if (i->bPush) + i->pCluster->DoActivate_Impl(pImp->pFrame, sal_True); + else + i->pCluster->DoDeactivate_Impl(pImp->pFrame, sal_True); } + aToDoCopy = aToDoCopyStack.back(); + aToDoCopyStack.pop_back(); + for(std::deque<SfxToDo_Impl>::reverse_iterator i = aToDoCopy.rbegin(); i != aToDoCopy.rend(); ++i) { - if(i->bDelete) + if (i->bDelete && !i->bDeleted) + { + if (!aToDoCopyStack.empty()) + { + //fdo#70703 if there is an outer FlushImpl then inform it that + //we have deleted this cluster + for (std::deque< std::deque<SfxToDo_Impl> >::iterator aI = aToDoCopyStack.begin(); + aI != aToDoCopyStack.end(); ++aI) + { + std::deque<SfxToDo_Impl> &v = *aI; + for(std::deque<SfxToDo_Impl>::iterator aJ = v.begin(); aJ != v.end(); ++aJ) + { + if (aJ->pCluster == i->pCluster) + aJ->bDeleted = true; + } + } + } delete i->pCluster; + } } sal_Bool bAwakeBindings = !aToDoCopy.empty(); if( bAwakeBindings ) |