[Libreoffice-commits] core.git: basic/inc basic/source dbaccess/source include/basic include/unotest sfx2/source unotest/source

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Sun Dec 29 14:46:52 UTC 2019


 basic/inc/sbxbase.hxx                          |    1 
 basic/source/basmgr/basicmanagerrepository.cxx |   20 ++++++++-
 basic/source/runtime/basrdll.cxx               |   53 +++++++++++++++----------
 basic/source/sbx/sbxbase.cxx                   |    3 +
 dbaccess/source/core/inc/databasecontext.hxx   |   10 ++++
 include/basic/basrdll.hxx                      |    7 +--
 include/unotest/macros_test.hxx                |   11 +++++
 sfx2/source/appl/app.cxx                       |    7 ---
 sfx2/source/appl/appdata.cxx                   |    7 +++
 unotest/source/cpp/macros_test.cxx             |    8 +++
 10 files changed, 92 insertions(+), 35 deletions(-)

New commits:
commit 8cce131dcc1803ac95f3079098be767662fcca09
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Sat Dec 28 03:49:16 2019 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Sun Dec 29 15:46:16 2019 +0100

    Avoid crash in shutdown when accessing already destroyed BASIC_DLL
    
    ... in ImplRepository::~ImplRepository.
    
    Running on Windows:
    make UITest_manual_tests UITEST_TEST_NAME=calc.ManualCalcTests.test_cell_recalc
    
    fails:
    
      ...
      Execution time for calc.ManualCalcTests.test_cell_recalc: 8.876
      tearDown: calling terminate()...
      ...done
      ERROR
    
      ======================================================================
      ERROR: test_cell_recalc (calc.ManualCalcTests)
      ----------------------------------------------------------------------
      Traceback (most recent call last):
        File "C:\lo\src\core\uitest\uitest\framework.py", line 46, in tearDown
          self.connection.tearDown()
        File "C:\lo\src\core\uitest\libreoffice\connection.py", line 178, in tearDown
          self.connection.tearDown()
        File "C:\lo\src\core\uitest\libreoffice\connection.py", line 138, in tearDown
          raise Exception("Exit status indicates failure: " + str(ret))
      Exception: Exit status indicates failure: 3221225477
    
      ----------------------------------------------------------------------
      Ran 1 test in 131.616s
    
      FAILED (errors=1)
      Tests run: 1
      Tests failed: 0
      Tests errors: 1
      Tests skipped: 0
    
    The call stack at the point of failure is
    
      sblo.dll!std::unique_ptr<SbxAppData,std::default_delete<SbxAppData>>::operator*() Line 1886
      sblo.dll!GetSbxData_Impl() Line 110
      sblo.dll!SbxBase::RemoveFactory(const SbxFactory * pFac) Line 122
      sblo.dll!StarBASIC::~StarBASIC() Line 964
      sblo.dll!StarBASIC::`vbase destructor'()
      sblo.dll!StarBASIC::`vector deleting destructor'(unsigned int)
      tllo.dll!SvRefBase::ReleaseRef() Line 163
      sblo.dll!tools::SvRef<StarBASIC>::~SvRef<StarBASIC>() Line 56
      sblo.dll!BasicLibInfo::~BasicLibInfo()
      sblo.dll!BasicLibInfo::`scalar deleting destructor'(unsigned int)
      sblo.dll!std::default_delete<BasicLibInfo>::operator()(BasicLibInfo * _Ptr) Line 1765
      sblo.dll!std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>::~unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>() Line 1875
      sblo.dll!std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>::`scalar deleting destructor'(unsigned int)
      sblo.dll!std::_Default_allocator_traits<std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>>::destroy<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>(std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>> & __formal, std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>> * const _Ptr) Line 677
      sblo.dll!std::_Destroy_range<std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>>(std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>> * _First, std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>> * const _Last, std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>> & _Al) Line 951
      sblo.dll!std::vector<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>,std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>>::_Destroy(std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>> * _First, std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>> * _Last) Line 1616
      sblo.dll!std::vector<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>,std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>>::_Tidy() Line 1698
      sblo.dll!std::vector<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>,std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>>::~vector<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>,std::allocator<std::unique_ptr<BasicLibInfo,std::default_delete<BasicLibInfo>>>>() Line 674
      sblo.dll!BasicManagerImpl::~BasicManagerImpl()
      sblo.dll!BasicManagerImpl::`scalar deleting destructor'(unsigned int)
      sblo.dll!std::default_delete<BasicManagerImpl>::operator()(BasicManagerImpl * _Ptr) Line 1765
      sblo.dll!std::unique_ptr<BasicManagerImpl,std::default_delete<BasicManagerImpl>>::~unique_ptr<BasicManagerImpl,std::default_delete<BasicManagerImpl>>() Line 1875
      sblo.dll!BasicManager::~BasicManager() Line 824
      sblo.dll!BasicManager::`vector deleting destructor'(unsigned int)
      sblo.dll!std::default_delete<BasicManager>::operator()(BasicManager * _Ptr) Line 1765
      sblo.dll!std::unique_ptr<BasicManager,std::default_delete<BasicManager>>::~unique_ptr<BasicManager,std::default_delete<BasicManager>>() Line 1875
      sblo.dll!std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>::~pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>()
      sblo.dll!std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>::`scalar deleting destructor'(unsigned int)
      sblo.dll!std::_Default_allocator_traits<std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>>>::destroy<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>(std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>> & __formal, std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>> * const _Ptr) Line 677
      sblo.dll!std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>::_Freenode<std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>>>(std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>> & _Al, std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *> * _Ptr) Line 379
      sblo.dll!std::_Tree<std::_Tmap_traits<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>,std::less<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>>,std::allocator<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>,0>>::_Erase_unchecked(std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>,std::_Iterator_base0> _Where) Line 1389
      sblo.dll!std::_Tree<std::_Tmap_traits<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>,std::less<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>>,std::allocator<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>,0>>::erase<std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>>,void>(std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>> _Where) Line 1417
      sblo.dll!basic::ImplRepository::Notify(SfxBroadcaster & _rBC, const SfxHint & _rHint) Line 580
      svllo.dll!SfxBroadcaster::Broadcast(const SfxHint & rHint) Line 50
      sblo.dll!BasicManager::~BasicManager() Line 823
      sblo.dll!BasicManager::`vector deleting destructor'(unsigned int)
      sblo.dll!std::default_delete<BasicManager>::operator()(BasicManager * _Ptr) Line 1765
      sblo.dll!std::unique_ptr<BasicManager,std::default_delete<BasicManager>>::~unique_ptr<BasicManager,std::default_delete<BasicManager>>() Line 1875
      sblo.dll!std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>::~pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>()
      sblo.dll!std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>::`scalar deleting destructor'(unsigned int)
      sblo.dll!std::_Default_allocator_traits<std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>>>::destroy<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>(std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>> & __formal, std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>> * const _Ptr) Line 677
      sblo.dll!std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>::_Freenode<std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>>>(std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>> & _Al, std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *> * _Ptr) Line 379
      sblo.dll!std::_Tree_val<std::_Tree_simple_types<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>::_Erase_tree<std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>>>(std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>> & _Al, std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *> * _Rootnode) Line 745
      sblo.dll!std::_Tree_val<std::_Tree_simple_types<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>::_Erase_head<std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>>>(std::allocator<std::_Tree_node<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>,void *>> & _Al) Line 753
      sblo.dll!std::_Tree<std::_Tmap_traits<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>,std::less<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>>,std::allocator<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>,0>>::~_Tree<std::_Tmap_traits<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>,std::less<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>>,std::allocator<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>,0>>() Line 1191
      sblo.dll!std::map<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>,std::less<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>>,std::allocator<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>::~map<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>,std::less<com::sun::star::uno::Reference<com::sun::star::uno::XInterface>>,std::allocator<std::pair<com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const ,std::unique_ptr<BasicManager,std::default_delete<BasicManager>>>>>()
      sblo.dll!basic::ImplRepository::~ImplRepository()
      sblo.dll!`basic::ImplRepository::Instance'::`2'::`dynamic atexit destructor for 'repository''()
      ucrtbased.dll!_execute_onexit_table::__l2::<lambda>() Line 206
      ucrtbased.dll!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) &,void <lambda>(void)>(__acrt_lock_and_call::__l2::void <lambda>(void) && setup, _execute_onexit_table::__l2::int <lambda>(void) & action, __acrt_lock_and_call::__l2::void <lambda>(void) && cleanup) Line 204
      ucrtbased.dll!__acrt_lock_and_call<int <lambda>(void)>(const __acrt_lock_id lock_id, _execute_onexit_table::__l2::int <lambda>(void) && action) Line 975
      ucrtbased.dll!_execute_onexit_table(_onexit_table_t * table) Line 231
      sblo.dll!__scrt_dllmain_uninitialize_c() Line 399
      sblo.dll!dllmain_crt_process_detach(const bool is_terminating) Line 182
      sblo.dll!dllmain_crt_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 220
      sblo.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 293
      sblo.dll!_DllMainCRTStartup(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 335
      ntdll.dll!LdrpCallInitRoutine()
      ntdll.dll!LdrShutdownProcess()
      ntdll.dll!RtlExitUserProcess()
      kernel32.dll!ExitProcessImplementation()
      ucrtbased.dll!exit_or_terminate_process(const unsigned int return_code) Line 144
      ucrtbased.dll!common_exit(const int return_code, const _crt_exit_cleanup_mode cleanup_mode, const _crt_exit_return_mode return_mode) Line 282
      ucrtbased.dll!exit(int return_code) Line 294
      soffice.bin!__scrt_common_main_seh() Line 297
      soffice.bin!__scrt_common_main() Line 331
      soffice.bin!mainCRTStartup() Line 17
      kernel32.dll!BaseThreadInitThunk()
      ntdll.dll!RtlUserThreadStart()
    
    Two problems here:
    1. Deleting a function-local static ImplRepository object happens after
    BASIC_DLL destruction either in SfxApplication::~SfxApplication or in
    MacroSnippet::~MacroSnippet, so BasicManager dtor indirectly trying to
    access BASIC_DLL segfaults.
    2. Implicit clearing of m_aStore in ImplRepository dtor calls dtors of
    owned BasicManager objects, which in turn notify parent ImplRepository,
    which again deletes the objects.
    
    This change limits lifetime of ImplRepository object with SbxAppData
    in BASIC_DLL, and avoids "owned BasicManager is deleting" notifications
    in its dtor.
    
    In dbaccess_complex test, ODatabaseContext accesses ImplRepository
    instance independently of SfxAppData_Impl lifetime: the latter is
    created before the former is created (and accesses ImplRepository
    instance first time), and destroyed before the former is destroyed
    (and accesses ImplRepository last time). So BASIC_DLL lifetime made
    ref-counted, to allow correct sharing of common instance between
    objects with independent lifetime.
    
    See also commit 3ebf6a090b227c0097ff8668fe023e7bdbdadc5d.
    
    Change-Id: I2ca36a87ddaf669557b3c3c7678e3d74aae66cce
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/85892
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/basic/inc/sbxbase.hxx b/basic/inc/sbxbase.hxx
index a4ea06678f27..269f6029a55a 100644
--- a/basic/inc/sbxbase.hxx
+++ b/basic/inc/sbxbase.hxx
@@ -40,6 +40,7 @@ struct SbxAppData
     SbxVariableRef      m_aGlobErr; // Global error object
     std::vector<std::unique_ptr<SbxFactory>>
                         m_Factories;
+    tools::SvRef<SvRefBase> mrImplRepository;
 
     // Pointer to Format()-Command helper class
     std::unique_ptr<SbxBasicFormater>   pBasicFormater;
diff --git a/basic/source/basmgr/basicmanagerrepository.cxx b/basic/source/basmgr/basicmanagerrepository.cxx
index 9116dbd382f1..01ca8759e145 100644
--- a/basic/source/basmgr/basicmanagerrepository.cxx
+++ b/basic/source/basmgr/basicmanagerrepository.cxx
@@ -22,6 +22,7 @@
 #include <scriptcont.hxx>
 #include <dlgcont.hxx>
 #include <sbintern.hxx>
+#include <sbxbase.hxx>
 
 #include <com/sun/star/document/XStorageBasedDocument.hpp>
 #include <com/sun/star/document/XEmbeddedScripts.hpp>
@@ -62,10 +63,11 @@ namespace basic
 
     typedef std::vector< BasicManagerCreationListener* >  CreationListeners;
 
-    class ImplRepository : public ::utl::OEventListenerAdapter, public SfxListener
+    class ImplRepository : public ::utl::OEventListenerAdapter, public SfxListener, public SvRefBase
     {
     private:
         ImplRepository();
+        ~ImplRepository();
 
     private:
         BasicManagerStore   m_aStore;
@@ -193,11 +195,23 @@ namespace basic
     {
     }
 
+    ImplRepository::~ImplRepository()
+    {
+        // Avoid double-delete of managers when they are destroyed in our dtor, and start notify us
+        for (auto& it : m_aStore)
+            EndListening(*it.second);
+    }
 
     ImplRepository& ImplRepository::Instance()
     {
-        static ImplRepository repository;
-        return repository;
+        tools::SvRef<SvRefBase>& repository = GetSbxData_Impl().mrImplRepository;
+        {
+            static osl::Mutex aMutex;
+            osl::MutexGuard aGuard(aMutex);
+            if (!repository)
+                repository = new ImplRepository;
+        }
+        return *static_cast<ImplRepository*>(repository.get());
     }
 
     BasicManager* ImplRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel )
diff --git a/basic/source/runtime/basrdll.cxx b/basic/source/runtime/basrdll.cxx
index a3145f404979..9fd82145afd2 100644
--- a/basic/source/runtime/basrdll.cxx
+++ b/basic/source/runtime/basrdll.cxx
@@ -28,69 +28,80 @@
 #include <sbxbase.hxx>
 #include <config_features.h>
 
-struct BasicDLL::Impl
+namespace
+{
+struct BasicDLLImpl : public SvRefBase
 {
     bool        bDebugMode;
     bool        bBreakEnabled;
 
     std::unique_ptr<SbxAppData> xSbxAppData;
 
-    Impl()
+    BasicDLLImpl()
         : bDebugMode(false)
         , bBreakEnabled(true)
         , xSbxAppData(new SbxAppData)
     { }
-};
-
-namespace {
 
-BasicDLL * BASIC_DLL;
+    static BasicDLLImpl* BASIC_DLL;
+    static osl::Mutex& getMutex()
+    {
+        static osl::Mutex aMutex;
+        return aMutex;
+    }
+};
 
+BasicDLLImpl* BasicDLLImpl::BASIC_DLL = nullptr;
 }
 
 BasicDLL::BasicDLL()
-    : m_xImpl(new Impl)
 {
-    BASIC_DLL = this;
+    osl::MutexGuard aGuard(BasicDLLImpl::getMutex());
+    if (!BasicDLLImpl::BASIC_DLL)
+        BasicDLLImpl::BASIC_DLL = new BasicDLLImpl;
+    m_xImpl = BasicDLLImpl::BASIC_DLL;
 }
 
 BasicDLL::~BasicDLL()
 {
+    osl::MutexGuard aGuard(BasicDLLImpl::getMutex());
+    const bool bLastRef = m_xImpl->GetRefCount() == 1;
+    m_xImpl.clear();
+    // only reset BASIC_DLL after the object had been destroyed
+    if (bLastRef)
+        BasicDLLImpl::BASIC_DLL = nullptr;
 }
 
 void BasicDLL::EnableBreak( bool bEnable )
 {
-    BasicDLL* pThis = BASIC_DLL;
-    DBG_ASSERT( pThis, "BasicDLL::EnableBreak: No instance yet!" );
-    if ( pThis )
+    DBG_ASSERT( BasicDLLImpl::BASIC_DLL, "BasicDLL::EnableBreak: No instance yet!" );
+    if (BasicDLLImpl::BASIC_DLL)
     {
-        pThis->m_xImpl->bBreakEnabled = bEnable;
+        BasicDLLImpl::BASIC_DLL->bBreakEnabled = bEnable;
     }
 }
 
 void BasicDLL::SetDebugMode( bool bDebugMode )
 {
-    BasicDLL* pThis = BASIC_DLL;
-    DBG_ASSERT( pThis, "BasicDLL::EnableBreak: No instance yet!" );
-    if ( pThis )
+    DBG_ASSERT( BasicDLLImpl::BASIC_DLL, "BasicDLL::EnableBreak: No instance yet!" );
+    if (BasicDLLImpl::BASIC_DLL)
     {
-        pThis->m_xImpl->bDebugMode = bDebugMode;
+        BasicDLLImpl::BASIC_DLL->bDebugMode = bDebugMode;
     }
 }
 
 
 void BasicDLL::BasicBreak()
 {
-    BasicDLL* pThis = BASIC_DLL;
-    DBG_ASSERT( pThis, "BasicDLL::EnableBreak: No instance yet!" );
+    DBG_ASSERT( BasicDLLImpl::BASIC_DLL, "BasicDLL::EnableBreak: No instance yet!" );
 #if HAVE_FEATURE_SCRIPTING
-    if ( pThis )
+    if (BasicDLLImpl::BASIC_DLL)
     {
         // bJustStopping: if there's someone pressing STOP like crazy umpteen times,
         // but the Basic doesn't stop early enough, the box might appear more often...
         static bool bJustStopping = false;
         if (StarBASIC::IsRunning() && !bJustStopping
-            && (pThis->m_xImpl->bBreakEnabled || pThis->m_xImpl->bDebugMode))
+            && (BasicDLLImpl::BASIC_DLL->bBreakEnabled || BasicDLLImpl::BASIC_DLL->bDebugMode))
         {
             bJustStopping = true;
             StarBASIC::Stop();
@@ -106,7 +117,7 @@ void BasicDLL::BasicBreak()
 
 SbxAppData& GetSbxData_Impl()
 {
-    return *BASIC_DLL->m_xImpl->xSbxAppData;
+    return *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 d1b17d4fa288..431a5ae5e612 100644
--- a/basic/source/sbx/sbxbase.cxx
+++ b/basic/source/sbx/sbxbase.cxx
@@ -46,6 +46,9 @@ SbxAppData::~SbxAppData()
     SolarMutexGuard g;
 
     pBasicFormater.reset();
+    m_aGlobErr.clear();
+    // basic manager repository must be destroyed before factories
+    mrImplRepository.clear();
     m_Factories.clear();
 }
 
diff --git a/dbaccess/source/core/inc/databasecontext.hxx b/dbaccess/source/core/inc/databasecontext.hxx
index 19c59a953f9d..6f5c2cb19d55 100644
--- a/dbaccess/source/core/inc/databasecontext.hxx
+++ b/dbaccess/source/core/inc/databasecontext.hxx
@@ -22,6 +22,8 @@
 
 #include <sal/config.h>
 
+#include <config_features.h>
+
 #include <map>
 
 #include "ModelImpl.hxx"
@@ -41,6 +43,10 @@
 #include <com/sun/star/uno/XNamingService.hpp>
 #include <com/sun/star/uno/XAggregation.hpp>
 
+#if HAVE_FEATURE_SCRIPTING
+#include <basic/basrdll.hxx>
+#endif
+
 #include <basic/basicmanagerrepository.hxx>
 #include <cppuhelper/compbase.hxx>
 #include <cppuhelper/interfacecontainer.hxx>
@@ -85,6 +91,10 @@ private:
     css::uno::Reference< css::uno::XInterface >
             impl_createNewDataSource();
 
+#if HAVE_FEATURE_SCRIPTING
+    BasicDLL m_aBasicDLL;
+#endif
+
 protected:
     ::osl::Mutex                    m_aMutex;
     css::uno::Reference< css::uno::XComponentContext >
diff --git a/include/basic/basrdll.hxx b/include/basic/basrdll.hxx
index e4e97ae65dbc..53768deb5760 100644
--- a/include/basic/basrdll.hxx
+++ b/include/basic/basrdll.hxx
@@ -21,13 +21,12 @@
 #define INCLUDED_BASIC_BASRDLL_HXX
 
 #include <basic/basicdllapi.h>
-#include <memory>
+#include <tools/ref.hxx>
 
 class BASIC_DLLPUBLIC BasicDLL
 {
-public:
-    struct Impl;
-    std::unique_ptr<Impl> m_xImpl;
+private:
+    tools::SvRef<SvRefBase> m_xImpl;
 
 public:
     BasicDLL();
diff --git a/include/unotest/macros_test.hxx b/include/unotest/macros_test.hxx
index 6ec5c25167df..4dcf9427fbf9 100644
--- a/include/unotest/macros_test.hxx
+++ b/include/unotest/macros_test.hxx
@@ -10,6 +10,9 @@
 #ifndef INCLUDED_UNOTEST_MACROS_TEST_HXX
 #define INCLUDED_UNOTEST_MACROS_TEST_HXX
 
+#include <sal/config.h>
+
+#include <memory>
 #include <rtl/ustring.hxx>
 #include <unotest/detail/unotestdllapi.hxx>
 
@@ -22,16 +25,24 @@ struct TestMacroInfo
     OUString sMacroUrl;
 };
 
+class BasicDLL;
+
 namespace unotest {
 
 class OOO_DLLPUBLIC_UNOTEST MacrosTest
 {
 public:
+    MacrosTest();
+    ~MacrosTest();
+
     css::uno::Reference< css::lang::XComponent > loadFromDesktop(const OUString& rURL, const OUString& rDocService = OUString(),
         const css::uno::Sequence<css::beans::PropertyValue>& rExtra_args = css::uno::Sequence<css::beans::PropertyValue>() );
 
 protected:
     css::uno::Reference< css::frame::XDesktop2> mxDesktop;
+
+private:
+    std::unique_ptr<BasicDLL> mpDll;
 };
 
 }
diff --git a/sfx2/source/appl/app.cxx b/sfx2/source/appl/app.cxx
index fafddce19064..c09b415825f6 100644
--- a/sfx2/source/appl/app.cxx
+++ b/sfx2/source/appl/app.cxx
@@ -24,7 +24,6 @@
 
 #include <sfx2/app.hxx>
 #include <sfx2/frame.hxx>
-#include <basic/basrdll.hxx>
 #include <basic/sberrors.hxx>
 #include <tools/svlibrary.h>
 
@@ -65,8 +64,6 @@ using namespace ::com::sun::star;
 
 static SfxApplication* g_pSfxApplication = nullptr;
 
-static BasicDLL*       pBasic   = nullptr;
-
 #if HAVE_FEATURE_DESKTOP
 static SfxHelp*        pSfxHelp = nullptr;
 #endif
@@ -160,8 +157,6 @@ SfxApplication::SfxApplication()
     pSfxHelp = new SfxHelp;
 #endif
 
-    pBasic   = new BasicDLL;
-
 #if HAVE_FEATURE_SCRIPTING
     StarBASIC::SetGlobalErrorHdl( LINK( this, SfxApplication, GlobalBasicErrorHdl_Impl ) );
 #endif
@@ -190,8 +185,6 @@ SfxApplication::~SfxApplication()
     if ( !pImpl->bDowning )
         Deinitialize();
 
-    delete pBasic;
-
     g_pSfxApplication = nullptr;
 }
 
diff --git a/sfx2/source/appl/appdata.cxx b/sfx2/source/appl/appdata.cxx
index e37fc0e1e73e..1b74848f39cf 100644
--- a/sfx2/source/appl/appdata.cxx
+++ b/sfx2/source/appl/appdata.cxx
@@ -31,6 +31,7 @@
 
 #include <basic/basicmanagerrepository.hxx>
 #include <basic/basmgr.hxx>
+#include <basic/basrdll.hxx>
 
 using ::basic::BasicManagerRepository;
 using ::basic::BasicManagerCreationListener;
@@ -38,6 +39,8 @@ using ::com::sun::star::uno::Reference;
 using ::com::sun::star::frame::XModel;
 using ::com::sun::star::uno::XInterface;
 
+static BasicDLL* pBasic = nullptr;
+
 class SfxBasicManagerCreationListener : public ::basic::BasicManagerCreationListener
 {
 private:
@@ -91,6 +94,8 @@ SfxAppData_Impl::SfxAppData_Impl()
     , bInQuit( false )
 
 {
+    pBasic = new BasicDLL;
+
 #if HAVE_FEATURE_SCRIPTING
     BasicManagerRepository::registerCreationListener( *pBasMgrListener );
 #endif
@@ -105,6 +110,8 @@ SfxAppData_Impl::~SfxAppData_Impl()
     BasicManagerRepository::revokeCreationListener( *pBasMgrListener );
     pBasMgrListener.reset();
 #endif
+
+    delete pBasic;
 }
 
 SfxDocumentTemplates* SfxAppData_Impl::GetDocumentTemplates()
diff --git a/unotest/source/cpp/macros_test.cxx b/unotest/source/cpp/macros_test.cxx
index ffc2b970393c..758dcc707347 100644
--- a/unotest/source/cpp/macros_test.cxx
+++ b/unotest/source/cpp/macros_test.cxx
@@ -14,6 +14,7 @@
 #include <com/sun/star/frame/XComponentLoader.hpp>
 #include <com/sun/star/document/MacroExecMode.hpp>
 
+#include <basic/basrdll.hxx>
 #include <cppunit/TestAssert.h>
 #include <rtl/ustrbuf.hxx>
 #include <comphelper/sequence.hxx>
@@ -22,6 +23,13 @@ using namespace css;
 
 namespace unotest {
 
+MacrosTest::MacrosTest()
+    : mpDll(std::make_unique<BasicDLL>())
+{
+}
+
+MacrosTest::~MacrosTest() = default;
+
 uno::Reference<css::lang::XComponent> MacrosTest::loadFromDesktop(const OUString& rURL, const OUString& rDocService, const uno::Sequence<beans::PropertyValue>& rExtraArgs)
 {
     CPPUNIT_ASSERT_MESSAGE("no desktop", mxDesktop.is());


More information about the Libreoffice-commits mailing list