diff options
author | Caolán McNamara <caolanm@redhat.com> | 2013-11-20 16:17:54 +0000 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2013-12-04 07:30:45 -0600 |
commit | 5d98639ec39f302df3dd38498703630e0556938d (patch) | |
tree | 43ce265a99f918a165df13978a0b81a3c48cf85d | |
parent | 99643319b62c3673b57f31d61a4619625747a444 (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
Reviewed-on: https://gerrit.libreoffice.org/6735
Reviewed-by: Michael Stahl <mstahl@redhat.com>
Tested-by: Michael Stahl <mstahl@redhat.com>
-rw-r--r-- | include/sfx2/dispatch.hxx | 33 | ||||
-rw-r--r-- | sfx2/source/control/dispatch.cxx | 72 |
2 files changed, 68 insertions, 37 deletions
diff --git a/include/sfx2/dispatch.hxx b/include/sfx2/dispatch.hxx index 2b02a5e620c6..4cf5fb176630 100644 --- a/include/sfx2/dispatch.hxx +++ b/include/sfx2/dispatch.hxx @@ -27,6 +27,7 @@ #include <sfx2/bindings.hxx> #include <sfx2/viewfrm.hxx> +#include <deque> #include <map> #include <vector> @@ -76,10 +77,38 @@ public: } }; +struct SfxToDo_Impl +{ + SfxShell* pCluster; + bool bPush; + bool bDelete; + bool bDeleted; + bool bUntil; + + SfxToDo_Impl() + : pCluster(0) + , bPush(false) + , bDelete(false) + , bDeleted(false) + , bUntil(false) + {} + SfxToDo_Impl( bool bOpPush, bool bOpDelete, bool bOpUntil, SfxShell& rCluster ) + : pCluster(&rCluster) + , bPush(bOpPush) + , bDelete(bOpDelete) + , bDeleted(false) + , bUntil(bOpUntil) + {} + + bool operator==( const SfxToDo_Impl& rWith ) const + { return pCluster==rWith.pCluster && bPush==rWith.bPush; } +}; + class SFX2_DLLPUBLIC SfxDispatcher { - SfxDispatcher_Impl* pImp; - sal_Bool bFlushed; + SfxDispatcher_Impl* pImp; + sal_Bool bFlushed; + std::deque< std::deque<SfxToDo_Impl> > aToDoCopyStack; private: // Search for temporary evaluated Todos diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx index 9acf705ee3be..3e10fff6be1f 100644 --- a/sfx2/source/control/dispatch.cxx +++ b/sfx2/source/control/dispatch.cxx @@ -67,31 +67,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 @@ -1625,22 +1600,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 ) |