crash on converting forums/ods/forum-en-39357.ods to xls, and on recalculating INDIRECT cells in 14 other documents, a debug build asserts: soffice.bin: svl/source/notify/lstner.cxx:83: void SfxListener::StartListening(SfxBroadcaster&, DuplicateHandling): Assertion `!(bListeningAlready && eDuplicateHanding == DuplicateHandling::Unexpected) && "duplicate listener, try building with DBG_UTIL to find the other insert site."' failed. #21 SfxListener::StartListening(SfxBroadcaster&, DuplicateHandling) at svl/source/notify/lstner.cxx:83 #22 SfxBasicManagerHolder::reset(BasicManager*) at sfx2/source/appl/appbaslib.cxx:70 #23 SfxObjectShell::InitBasicManager_Impl() at sfx2/source/doc/objxtor.cxx:845 #24 lcl_getBasicManagerForDocument(SfxObjectShell const&) at sfx2/source/doc/objxtor.cxx:656 #25 SfxObjectShell::GetBasicManager() const at sfx2/source/doc/objxtor.cxx:690 #26 SfxObjectShell::GetBasic() const at sfx2/source/doc/objxtor.cxx:799 #27 ScCompiler::ParseMacro(rtl::OUString const&, bool) at sc/source/core/tool/compiler.cxx:3830 #28 ScCompiler::NextNewToken(bool) at sc/source/core/tool/compiler.cxx:5137 #29 ScCompiler::CompileString(rtl::OUString const&) at sc/source/core/tool/compiler.cxx:5293 #30 XclExpChSourceLink::ConvertDataSequence(...) at sc/source/filter/excel/xechart.cxx:901 and the first StartListening of the pair was: SfxBasicManagerHolder::reset(BasicManager*) at sfx2/source/appl/appbaslib.cxx:71 SfxObjectShell::InitBasicManager_Impl() at sfx2/source/doc/objxtor.cxx:845 lcl_getBasicManagerForDocument(SfxObjectShell const&) at sfx2/source/doc/objxtor.cxx:657 SfxObjectShell::GetBasicManager() const at sfx2/source/doc/objxtor.cxx:690 ScServiceProvider::MakeInstance(ScServiceProvider::Type, ScDocShell*) at sc/source/ui/unoobj/servuno.cxx:590 ScModelObj::createInstance(rtl::OUString const&) at sc/source/ui/unoobj/docuno.cxx:4085 basic::SfxScriptLibraryContainer::importLibraryElement(...) Creating the BasicManager of a VBA mode document loads its VBA document modules, and they create the VBA globals, which asks for the document's BasicManager again. That nested InitBasicManager_Impl gets the BasicManager under construction from the repository and passes it to the holder, then the outer one passes the same one again, so the holder starts listening to it twice. That recursion is old, but crashtesting only reaches it since: commit c8da2d3a99b3a318545f1947f57c929ac9b9a82d Date: Sat Sep 26 20:23:11 2026 +0000 load the Basic project of a VBA mode Calc document after import Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/13614 Previously the import loaded the Basic project at once and the first request for the BasicManager came from inside that load. Now with macros not allowed the project stays unloaded, so the first request comes later, from a formula, and the load runs inside it. so make SfxBasicManagerHolder::reset do nothing when it is given the BasicManager it already holds Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com> Change-Id: I5db2184ae0124879e47310d90b5371e1e2fb0235 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/14516 Reviewed-by: Noel Grandin <noel.grandin@collabora.com> Tested-by: Jenkins CPCI <releng@collaboraoffice.com> (cherry picked from commit a095496e0d649882531fd8e211ec4179333adee0) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211941 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Jenkins
186 lines
5.7 KiB
C++
186 lines
5.7 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <config_features.h>
|
|
|
|
#include <appbaslib.hxx>
|
|
|
|
#include <sfx2/app.hxx>
|
|
|
|
#include <basic/basmgr.hxx>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <com/sun/star/uno/XComponentContext.hpp>
|
|
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::script;
|
|
using namespace ::com::sun::star::embed;
|
|
|
|
|
|
SfxBasicManagerHolder::SfxBasicManagerHolder()
|
|
:mpBasicManager( nullptr )
|
|
{
|
|
}
|
|
|
|
void SfxBasicManagerHolder::Notify(SfxBroadcaster& rBC, SfxHint const& rHint)
|
|
{
|
|
if (!mpBasicManager || &rBC != mpBasicManager)
|
|
return;
|
|
if (SfxHintId::Dying == rHint.GetId())
|
|
{
|
|
mpBasicManager = nullptr;
|
|
mxBasicContainer.clear();
|
|
mxDialogContainer.clear();
|
|
}
|
|
}
|
|
|
|
void SfxBasicManagerHolder::reset( BasicManager* _pBasicManager )
|
|
{
|
|
// A document's Basic manager can be handed over a second time while it is still being
|
|
// created. The holder already listens to it and holds its containers, so it stays as it is.
|
|
if ( _pBasicManager == mpBasicManager )
|
|
return;
|
|
|
|
impl_releaseContainers();
|
|
|
|
#if !HAVE_FEATURE_SCRIPTING
|
|
(void) _pBasicManager;
|
|
#else
|
|
// Note: we do not delete the old BasicManager. BasicManager instances are
|
|
// nowadays obtained from the BasicManagerRepository, and the ownership is with
|
|
// the repository.
|
|
// @see basic::BasicManagerRepository::getApplicationBasicManager
|
|
// @see basic::BasicManagerRepository::getDocumentBasicManager
|
|
mpBasicManager = _pBasicManager;
|
|
|
|
if ( !mpBasicManager )
|
|
return;
|
|
|
|
StartListening(*mpBasicManager);
|
|
mxBasicContainer.set( mpBasicManager->GetScriptLibraryContainer() );
|
|
mxDialogContainer.set( mpBasicManager->GetDialogLibraryContainer() );
|
|
#endif
|
|
}
|
|
|
|
void SfxBasicManagerHolder::storeAllLibraries()
|
|
{
|
|
#if HAVE_FEATURE_SCRIPTING
|
|
OSL_PRECOND( isValid(), "SfxBasicManagerHolder::storeAllLibraries: not initialized!" );
|
|
try
|
|
{
|
|
if ( mxBasicContainer.is() )
|
|
mxBasicContainer->storeLibraries();
|
|
if ( mxDialogContainer.is() )
|
|
mxDialogContainer->storeLibraries();
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("sfx.appl");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SfxBasicManagerHolder::setStorage( const Reference< XStorage >& _rxStorage )
|
|
{
|
|
#if !HAVE_FEATURE_SCRIPTING
|
|
(void) _rxStorage;
|
|
#else
|
|
try
|
|
{
|
|
if ( mxBasicContainer.is() )
|
|
mxBasicContainer->setRootStorage( _rxStorage );
|
|
if ( mxDialogContainer.is() )
|
|
mxDialogContainer->setRootStorage( _rxStorage );
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("sfx.appl");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SfxBasicManagerHolder::storeLibrariesToStorage( const Reference< XStorage >& _rxStorage )
|
|
{
|
|
#if !HAVE_FEATURE_SCRIPTING
|
|
(void) _rxStorage;
|
|
#else
|
|
OSL_PRECOND( isValid(), "SfxBasicManagerHolder::storeLibrariesToStorage: not initialized!" );
|
|
|
|
if ( mxBasicContainer.is() )
|
|
mxBasicContainer->storeLibrariesToStorage( _rxStorage );
|
|
if ( mxDialogContainer.is() )
|
|
mxDialogContainer->storeLibrariesToStorage( _rxStorage );
|
|
#endif
|
|
}
|
|
|
|
XStorageBasedLibraryContainer* SfxBasicManagerHolder::getLibraryContainer( ContainerType _eType )
|
|
{
|
|
OSL_PRECOND( isValid(), "SfxBasicManagerHolder::getLibraryContainer: not initialized!" );
|
|
|
|
switch ( _eType )
|
|
{
|
|
case SCRIPTS: return mxBasicContainer.get();
|
|
case DIALOGS: return mxDialogContainer.get();
|
|
}
|
|
OSL_FAIL( "SfxBasicManagerHolder::getLibraryContainer: illegal container type!" );
|
|
return nullptr;
|
|
}
|
|
|
|
void SfxBasicManagerHolder::impl_releaseContainers()
|
|
{
|
|
mxBasicContainer.clear();
|
|
mxDialogContainer.clear();
|
|
}
|
|
|
|
bool SfxBasicManagerHolder::ImgVersion12PsswdBinaryLimitExceeded( std::vector< OUString >& sModules )
|
|
{
|
|
#if !HAVE_FEATURE_SCRIPTING
|
|
(void) sModules;
|
|
#else
|
|
if ( mpBasicManager )
|
|
return mpBasicManager->ImgVersion12PsswdBinaryLimitExceeded( sModules );
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
// Service for application library container
|
|
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
|
|
com_sun_star_comp_sfx2_ApplicationDialogLibraryContainer_get_implementation(
|
|
css::uno::XComponentContext *,
|
|
css::uno::Sequence<css::uno::Any> const &)
|
|
{
|
|
SfxApplication::GetBasicManager();
|
|
css::uno::XInterface* pRet = static_cast<css::script::XLibraryContainer*>(SfxGetpApp()->GetDialogContainer());
|
|
pRet->acquire();
|
|
return pRet;
|
|
}
|
|
|
|
// Service for application library container
|
|
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
|
|
com_sun_star_comp_sfx2_ApplicationScriptLibraryContainer_get_implementation(
|
|
css::uno::XComponentContext *,
|
|
css::uno::Sequence<css::uno::Any> const &)
|
|
{
|
|
SfxApplication::GetBasicManager();
|
|
css::uno::XInterface* pRet = static_cast<css::script::XLibraryContainer*>(SfxGetpApp()->GetBasicContainer());
|
|
pRet->acquire();
|
|
return pRet;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|