fix shutdown crash in basic
another change I am working on slightly tweaks the shutdown ordering
and exposes this problem where two classes both think they own
the same object.
Change-Id: I7477cf7eda5b5729ee3861cb4a1be43bb34d9ea6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99724
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/basic/inc/sbxbase.hxx b/basic/inc/sbxbase.hxx
index 269f602..361dd52 100644
--- a/basic/inc/sbxbase.hxx
+++ b/basic/inc/sbxbase.hxx
@@ -38,9 +38,8 @@ struct SbxAppData
{
ErrCode eErrCode; // Error code
SbxVariableRef m_aGlobErr; // Global error object
std::vector<std::unique_ptr<SbxFactory>>
m_Factories;
tools::SvRef<SvRefBase> mrImplRepository;
std::vector<SbxFactory*> m_Factories; // these are owned by
tools::SvRef<SvRefBase> mrImplRepository;
// Pointer to Format()-Command helper class
std::unique_ptr<SbxBasicFormater> pBasicFormater;
@@ -55,6 +54,8 @@ struct SbxAppData
};
SbxAppData& GetSbxData_Impl();
/** returns true if the SbxAppData is still valid, used to check if we are in shutdown. */
bool IsSbxData_Impl();
#endif // INCLUDED_BASIC_INC_SBXBASE_HXX
diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx
index 1de6c820..c9f34e9 100644
--- a/basic/source/classes/sb.cxx
+++ b/basic/source/classes/sb.cxx
@@ -463,14 +463,6 @@ SbxObject* SbiFactory::CreateObject( const OUString& rClass )
}
// Factory class to create OLE objects
class SbOLEFactory : public SbxFactory
{
public:
virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 ) override;
virtual SbxObject* CreateObject( const OUString& ) override;
};
SbxBase* SbOLEFactory::Create( sal_uInt16, sal_uInt32 )
{
// Not supported
@@ -486,13 +478,6 @@ SbxObject* SbOLEFactory::CreateObject( const OUString& rClassName )
// SbFormFactory, show user forms by: dim as new <user form name>
class SbFormFactory : public SbxFactory
{
public:
virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 ) override;
virtual SbxObject* CreateObject( const OUString& ) override;
};
SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 )
{
// Not supported
@@ -587,14 +572,6 @@ SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj )
return pRet;
}
// Factory class to create user defined objects (type command)
class SbTypeFactory : public SbxFactory
{
public:
virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 ) override;
virtual SbxObject* CreateObject( const OUString& ) override;
};
SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 )
{
// Not supported
@@ -922,14 +899,14 @@ StarBASIC::StarBASIC( StarBASIC* p, bool bIsDocBasic )
{
GetSbData()->pSbFac.reset( new SbiFactory );
AddFactory( GetSbData()->pSbFac.get() );
GetSbData()->pTypeFac = new SbTypeFactory;
AddFactory( GetSbData()->pTypeFac );
GetSbData()->pClassFac = new SbClassFactory;
AddFactory( GetSbData()->pClassFac );
GetSbData()->pOLEFac = new SbOLEFactory;
AddFactory( GetSbData()->pOLEFac );
GetSbData()->pFormFac = new SbFormFactory;
AddFactory( GetSbData()->pFormFac );
GetSbData()->pTypeFac.reset(new SbTypeFactory);
AddFactory( GetSbData()->pTypeFac.get() );
GetSbData()->pClassFac.reset(new SbClassFactory);
AddFactory( GetSbData()->pClassFac.get() );
GetSbData()->pOLEFac.reset(new SbOLEFactory);
AddFactory( GetSbData()->pOLEFac.get() );
GetSbData()->pFormFac.reset(new SbFormFactory);
AddFactory( GetSbData()->pFormFac.get() );
GetSbData()->pUnoFac.reset( new SbUnoFactory );
AddFactory( GetSbData()->pUnoFac.get() );
}
@@ -963,14 +940,14 @@ StarBASIC::~StarBASIC()
GetSbData()->pSbFac.reset();
RemoveFactory( GetSbData()->pUnoFac.get() );
GetSbData()->pUnoFac.reset();
RemoveFactory( GetSbData()->pTypeFac );
delete GetSbData()->pTypeFac; GetSbData()->pTypeFac = nullptr;
RemoveFactory( GetSbData()->pClassFac );
delete GetSbData()->pClassFac; GetSbData()->pClassFac = nullptr;
RemoveFactory( GetSbData()->pOLEFac );
delete GetSbData()->pOLEFac; GetSbData()->pOLEFac = nullptr;
RemoveFactory( GetSbData()->pFormFac );
delete GetSbData()->pFormFac; GetSbData()->pFormFac = nullptr;
RemoveFactory( GetSbData()->pTypeFac.get() );
GetSbData()->pTypeFac.reset();
RemoveFactory( GetSbData()->pClassFac.get() );
GetSbData()->pClassFac.reset();
RemoveFactory( GetSbData()->pOLEFac.get() );
GetSbData()->pOLEFac.reset();
RemoveFactory( GetSbData()->pFormFac.get() );
GetSbData()->pFormFac.reset();
if( SbiGlobals::pGlobals )
{
diff --git a/basic/source/inc/sbintern.hxx b/basic/source/inc/sbintern.hxx
index 75e3ede..9a04368 100644
--- a/basic/source/inc/sbintern.hxx
+++ b/basic/source/inc/sbintern.hxx
@@ -78,16 +78,45 @@ public:
SbModule* FindClass( const OUString& rClassName );
};
// Factory class to create user defined objects (type command)
class SbTypeFactory : public SbxFactory
{
public:
virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 ) override;
virtual SbxObject* CreateObject( const OUString& ) override;
};
class SbFormFactory : public SbxFactory
{
public:
virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 ) override;
virtual SbxObject* CreateObject( const OUString& ) override;
};
// Factory class to create OLE objects
class SbOLEFactory : public SbxFactory
{
public:
virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 ) override;
virtual SbxObject* CreateObject( const OUString& ) override;
};
struct SbiGlobals
{
static SbiGlobals* pGlobals;
SbiInstance* pInst; // all active runtime instances
std::unique_ptr<SbiFactory> pSbFac; // StarBASIC-Factory
std::unique_ptr<SbUnoFactory> pUnoFac; // Factory for Uno-Structs at DIM AS NEW
SbTypeFactory* pTypeFac; // Factory for user defined types
SbClassFactory* pClassFac; // Factory for user defined classes (based on class modules)
SbOLEFactory* pOLEFac; // Factory for OLE types
SbFormFactory* pFormFac; // Factory for user forms
std::unique_ptr<SbTypeFactory>
pTypeFac; // Factory for user defined types
std::unique_ptr<SbClassFactory>
pClassFac; // Factory for user defined classes (based on class modules)
std::unique_ptr<SbOLEFactory>
pOLEFac; // Factory for OLE types
std::unique_ptr<SbFormFactory>
pFormFac; // Factory for user forms
SbModule* pMod; // currently active module
SbModule* pCompMod; // currently compiled module
short nInst; // number of BASICs
diff --git a/basic/source/runtime/basrdll.cxx b/basic/source/runtime/basrdll.cxx
index 6da6ed9..29cd292 100644
--- a/basic/source/runtime/basrdll.cxx
+++ b/basic/source/runtime/basrdll.cxx
@@ -123,4 +123,9 @@ SbxAppData& GetSbxData_Impl()
return *BasicDLLImpl::BASIC_DLL->xSbxAppData;
}
bool IsSbxData_Impl()
{
return BasicDLLImpl::BASIC_DLL && BasicDLLImpl::BASIC_DLL->xSbxAppData;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxbase.cxx b/basic/source/sbx/sbxbase.cxx
index c80b681..f62949a 100644
--- a/basic/source/sbx/sbxbase.cxx
+++ b/basic/source/sbx/sbxbase.cxx
@@ -48,7 +48,9 @@ SbxAppData::~SbxAppData()
pBasicFormater.reset();
// basic manager repository must be destroyed before factories
mrImplRepository.clear();
m_Factories.clear();
// we need to move stuff out otherwise the destruction of the factories
// calls back into SbxBase::RemoveFactory and sees partially destructed data
std::move(m_Factories);
}
SbxBase::SbxBase()
@@ -121,15 +123,12 @@ void SbxBase::AddFactory( SbxFactory* pFac )
void SbxBase::RemoveFactory( SbxFactory const * pFac )
{
if (!IsSbxData_Impl())
return;
SbxAppData& r = GetSbxData_Impl();
auto it = std::find_if(r.m_Factories.begin(), r.m_Factories.end(),
[&pFac](const std::unique_ptr<SbxFactory>& rxFactory) { return rxFactory.get() == pFac; });
auto it = std::find(r.m_Factories.begin(), r.m_Factories.end(), pFac);
if (it != r.m_Factories.end())
{
std::unique_ptr<SbxFactory> tmp(std::move(*it));
r.m_Factories.erase( it );
(void)tmp.release();
}
}