Kaydet (Commit) df5f7c6a authored tarafından Henry Castro's avatar Henry Castro Kaydeden (comit) Tor Lillqvist

Introduce lok_preinit() to preload all registered UNO implementations

Intended to be used from an application like the LibreOffice On-Line
server so that it can be called in a process that then will call
fork() several times, and much space consuming data will end up being
shared.

Change-Id: I65341c57d00308d246ec90deab8050b2c4bb3e61
üst 5b0c551b
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/XSingleComponentFactory.hpp> #include <com/sun/star/lang/XSingleComponentFactory.hpp>
#include <cppuhelper/bootstrap.hxx> #include <cppuhelper/bootstrap.hxx>
#include <cppuhelper/detail/preinit.hxx>
#include <cppuhelper/component_context.hxx> #include <cppuhelper/component_context.hxx>
#include <rtl/bootstrap.hxx> #include <rtl/bootstrap.hxx>
#include <rtl/ref.hxx> #include <rtl/ref.hxx>
...@@ -107,4 +108,19 @@ cppu::defaultBootstrap_InitialComponentContext() ...@@ -107,4 +108,19 @@ cppu::defaultBootstrap_InitialComponentContext()
return defaultBootstrap_InitialComponentContext(getUnoIniUri()); return defaultBootstrap_InitialComponentContext(getUnoIniUri());
} }
void
cppu::preInitBootstrap()
{
rtl::OUString iniUri(getUnoIniUri());
rtl::Bootstrap bs(iniUri);
if (bs.getHandle() == nullptr)
throw css::uno::DeploymentException("Cannot open uno ini " + iniUri);
// create the service manager
rtl::Reference< cppuhelper::ServiceManager > aManager(new cppuhelper::ServiceManager);
// read rdb files
aManager->init(getBootstrapVariable(bs, "UNO_SERVICES"));
aManager->loadAllImplementations();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -436,3 +436,8 @@ GLIBCXX_3.4 { ...@@ -436,3 +436,8 @@ GLIBCXX_3.4 {
_ZGVNSt7num_put*; _ZNSt7num_put*; _ZGVNSt7num_put*; _ZNSt7num_put*;
_ZNSs4_Rep20_S_empty_rep_storageE; _ZNSs4_Rep20_S_empty_rep_storageE;
}; };
PRIVATE_1.0 { # LibO 5.2
global:
_ZN4cppu16preInitBootstrapEv;
};
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <cppuhelper/implbase3.hxx> #include <cppuhelper/implbase3.hxx>
#include <cppuhelper/supportsservice.hxx> #include <cppuhelper/supportsservice.hxx>
#include <osl/file.hxx> #include <osl/file.hxx>
#include <osl/module.hxx>
#include <rtl/ref.hxx> #include <rtl/ref.hxx>
#include <rtl/uri.hxx> #include <rtl/uri.hxx>
#include <rtl/ustring.hxx> #include <rtl/ustring.hxx>
...@@ -875,6 +876,40 @@ void cppuhelper::ServiceManager::loadImplementation( ...@@ -875,6 +876,40 @@ void cppuhelper::ServiceManager::loadImplementation(
} }
} }
void cppuhelper::ServiceManager::loadAllImplementations()
{
rtl::OUString aUri;
osl::MutexGuard g(rBHelper.rMutex);
for (Data::NamedImplementations::const_iterator iterator(
data_.namedImplementations.begin());
iterator != data_.namedImplementations.end(); ++iterator)
{
try
{
aUri = cppu::bootstrap_expandUri(iterator->second->info->uri);
}
catch (css::lang::IllegalArgumentException& aError)
{
throw css::uno::DeploymentException(
"Cannot expand URI" + iterator->second->info->uri + ": " + aError.Message,
static_cast< cppu::OWeakObject * >(this));
}
if (iterator->second->info->loader == "com.sun.star.loader.SharedLibrary" &&
iterator->second->status != Data::Implementation::STATUS_LOADED)
{
oslModule aModule = osl_loadModule( aUri.pData, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL );
SAL_INFO("lok", "loaded component library " << aUri << ( aModule ? " ok" : " no"));
// leak aModule
// osl_unloadModule(aModule);
if ( aModule )
iterator->second->status = Data::Implementation::STATUS_LOADED;
}
}
}
void cppuhelper::ServiceManager::disposing() { void cppuhelper::ServiceManager::disposing() {
std::vector< css::uno::Reference<css::lang::XComponent> > sngls; std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
std::vector< css::uno::Reference< css::lang::XComponent > > comps; std::vector< css::uno::Reference< css::lang::XComponent > > comps;
......
...@@ -203,6 +203,8 @@ public: ...@@ -203,6 +203,8 @@ public:
css::uno::Reference< css::uno::XComponentContext > const & context, css::uno::Reference< css::uno::XComponentContext > const & context,
std::shared_ptr< Data::Implementation > & implementation); std::shared_ptr< Data::Implementation > & implementation);
void loadAllImplementations();
private: private:
virtual ~ServiceManager(); virtual ~ServiceManager();
......
...@@ -59,6 +59,7 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\ ...@@ -59,6 +59,7 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\
ucbhelper \ ucbhelper \
utl \ utl \
vcl \ vcl \
xmlreader \
$(gb_UWINAPI) \ $(gb_UWINAPI) \
)) ))
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <rtl/strbuf.hxx> #include <rtl/strbuf.hxx>
#include <rtl/uri.hxx> #include <rtl/uri.hxx>
#include <cppuhelper/bootstrap.hxx> #include <cppuhelper/bootstrap.hxx>
#include <cppuhelper/detail/preinit.hxx>
#include <comphelper/dispatchcommand.hxx> #include <comphelper/dispatchcommand.hxx>
#include <comphelper/lok.hxx> #include <comphelper/lok.hxx>
#include <comphelper/processfactory.hxx> #include <comphelper/processfactory.hxx>
...@@ -47,6 +48,8 @@ ...@@ -47,6 +48,8 @@
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp> #include <com/sun/star/ucb/XContentProvider.hpp>
#include <com/sun/star/ucb/XUniversalContentBroker.hpp> #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/util/URLTransformer.hpp> #include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp> #include <com/sun/star/text/TextContentAnchorType.hpp>
...@@ -1772,6 +1775,7 @@ static bool initialize_uno(const OUString& aAppProgramURL) ...@@ -1772,6 +1775,7 @@ static bool initialize_uno(const OUString& aAppProgramURL)
#endif #endif
xContext = cppu::defaultBootstrap_InitialComponentContext(); xContext = cppu::defaultBootstrap_InitialComponentContext();
if (!xContext.is()) if (!xContext.is())
{ {
gImpl->maLastExceptionMsg = "XComponentContext could not be created"; gImpl->maLastExceptionMsg = "XComponentContext could not be created";
...@@ -1804,6 +1808,9 @@ static void lo_startmain(void*) ...@@ -1804,6 +1808,9 @@ static void lo_startmain(void*)
{ {
osl_setThreadName("lo_startmain"); osl_setThreadName("lo_startmain");
if (GetpApp())
Application::GetSolarMutex().tryToAcquire();
soffice_main(); soffice_main();
} }
...@@ -1832,19 +1839,38 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit: ...@@ -1832,19 +1839,38 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit:
static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char* pUserProfilePath) static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char* pUserProfilePath)
{ {
enum {
PRE_INIT, // setup shared data in master process
SECOND_INIT, // complete init. after fork
FULL_INIT // do a standard complete init.
} eStage;
// Did we do a pre-initialize
static bool bPreInited = false;
// What stage are we at ?
if (pThis == NULL)
eStage = PRE_INIT;
else if (bPreInited)
eStage = SECOND_INIT;
else
eStage = FULL_INIT;
LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis); LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis);
if (bInitialized) if (bInitialized)
return 1; return 1;
comphelper::LibreOfficeKit::setActive(); if (eStage != SECOND_INIT)
comphelper::LibreOfficeKit::setActive();
static bool bViewCallback = getenv("LOK_VIEW_CALLBACK"); static bool bViewCallback = getenv("LOK_VIEW_CALLBACK");
comphelper::LibreOfficeKit::setViewCallback(bViewCallback); comphelper::LibreOfficeKit::setViewCallback(bViewCallback);
comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib); if (eStage != PRE_INIT)
comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib);
if (pUserProfilePath) if (eStage != SECOND_INIT && pUserProfilePath)
rtl::Bootstrap::set("UserInstallation", OUString(pUserProfilePath, strlen(pUserProfilePath), RTL_TEXTENCODING_UTF8)); rtl::Bootstrap::set("UserInstallation", OUString(pUserProfilePath, strlen(pUserProfilePath), RTL_TEXTENCODING_UTF8));
OUString aAppPath; OUString aAppPath;
...@@ -1867,22 +1893,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char ...@@ -1867,22 +1893,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
try try
{ {
SAL_INFO("lok", "Attempting to initialize UNO"); if (eStage != SECOND_INIT)
if (!initialize_uno(aAppURL))
{ {
return false; SAL_INFO("lok", "Attempting to initialize UNO");
}
force_c_locale(); if (!initialize_uno(aAppURL))
return false;
// Force headless -- this is only for bitmap rendering. // Force headless -- this is only for bitmap rendering.
rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp"); rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp");
// We specifically need to make sure we have the "headless" // We specifically need to make sure we have the "headless"
// command arg set (various code specifically checks via // command arg set (various code specifically checks via
// CommandLineArgs): // CommandLineArgs):
desktop::Desktop::GetCommandLineArgs().setHeadless(); desktop::Desktop::GetCommandLineArgs().setHeadless();
Application::EnableHeadlessMode(true); Application::EnableHeadlessMode(true);
if (eStage == PRE_INIT)
{
InitVCL();
// pre-load all component libraries.
cppu::preInitBootstrap();
// Release Solar Mutex, lo_startmain thread should acquire it.
Application::ReleaseSolarMutex();
}
force_c_locale();
}
// This is horrible crack. I really would want to go back to simply just call // This is horrible crack. I really would want to go back to simply just call
// InitVCL() here. The OfficeIPCThread thing is just horrible. // InitVCL() here. The OfficeIPCThread thing is just horrible.
...@@ -1903,27 +1941,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char ...@@ -1903,27 +1941,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
// the Thread from wherever (it's done again in Desktop::Main), and can // the Thread from wherever (it's done again in Desktop::Main), and can
// then use it to wait until we're definitely ready to continue. // then use it to wait until we're definitely ready to continue.
SAL_INFO("lok", "Enabling OfficeIPCThread"); if (eStage != PRE_INIT)
OfficeIPCThread::EnableOfficeIPCThread();
SAL_INFO("lok", "Starting soffice_main");
pLib->maThread = osl_createThread(lo_startmain, nullptr);
SAL_INFO("lok", "Waiting for OfficeIPCThread");
OfficeIPCThread::WaitForReady();
SAL_INFO("lok", "OfficeIPCThread ready -- continuing");
// If the Thread has been disabled again that indicates that a
// restart is required (or in any case we don't have a useable
// process around).
if (!OfficeIPCThread::IsEnabled())
{ {
fprintf(stderr, "LOK init failed -- restart required\n"); SAL_INFO("lok", "Enabling OfficeIPCThread");
return false; OfficeIPCThread::EnableOfficeIPCThread();
SAL_INFO("lok", "Starting soffice_main");
pLib->maThread = osl_createThread(lo_startmain, nullptr);
SAL_INFO("lok", "Waiting for OfficeIPCThread");
OfficeIPCThread::WaitForReady();
SAL_INFO("lok", "OfficeIPCThread ready -- continuing");
// If the Thread has been disabled again that indicates that a
// restart is required (or in any case we don't have a useable
// process around).
if (!OfficeIPCThread::IsEnabled())
{
fprintf(stderr, "LOK init failed -- restart required\n");
return false;
}
} }
ErrorHandler::RegisterDisplay(aBasicErrorFunc); if (eStage != SECOND_INIT)
ErrorHandler::RegisterDisplay(aBasicErrorFunc);
SAL_INFO("lok", "LOK Initialized"); SAL_INFO("lok", "LOK Initialized");
bInitialized = true; if (eStage == PRE_INIT)
bPreInited = true;
else
bInitialized = true;
} }
catch (css::uno::Exception& exception) catch (css::uno::Exception& exception)
{ {
...@@ -1971,6 +2016,12 @@ LibreOfficeKit *libreofficekit_hook(const char* install_path) ...@@ -1971,6 +2016,12 @@ LibreOfficeKit *libreofficekit_hook(const char* install_path)
return libreofficekit_hook_2(install_path, nullptr); return libreofficekit_hook_2(install_path, nullptr);
} }
SAL_JNI_EXPORT
int lok_preinit(const char* install_path, const char* user_profile_path)
{
return lo_initialize(NULL, install_path, user_profile_path);
}
static void lo_destroy(LibreOfficeKit* pThis) static void lo_destroy(LibreOfficeKit* pThis)
{ {
LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis); LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis);
......
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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/.
*/
#ifndef INCLUDED_CPPUHELPER_DETAIL_PREINIT_HXX
#define INCLUDED_CPPUHELPER_DETAIL_PREINIT_HXX
#include <cppuhelper/cppuhelperdllapi.h>
namespace cppu
{
#if defined LIBO_INTERNAL_ONLY
CPPUHELPER_DLLPUBLIC void SAL_CALL
preInitBootstrap();
#endif // LIBO_INTERNAL_ONLY
} // namespace cppu
#endif // INCLUDED_CPPUHELPER_DETAIL_PREINIT_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -82,7 +82,29 @@ int main (int argc, char **argv) ...@@ -82,7 +82,29 @@ int main (int argc, char **argv)
return 1; return 1;
// coverity[tainted_string] - build time test tool // coverity[tainted_string] - build time test tool
Office *pOffice = lok_cpp_init( argv[1] ); char *install_path = argv[1];
if( argc > 4 )
{
fprintf( stderr, "testing preinit\n");
char *imp_lib;
void *dlhandle;
dlhandle = lok_dlopen( install_path, &imp_lib );
if( !dlhandle )
{
fprintf( stderr, "Failed to link '%s'\n", lok_dlerror() );
return -1;
}
LokHookPreInit *preinit = (LokHookPreInit *) lok_dlsym( dlhandle, "lok_preinit" );
if( !preinit )
{
fprintf( stderr, "Failed to find pre-init symbol: %s\n", lok_dlerror() );
return -1;
}
preinit( install_path, NULL );
}
Office *pOffice = lok_cpp_init( install_path );
if( !pOffice ) if( !pOffice )
{ {
fprintf( stderr, "Failed to initialize\n" ); fprintf( stderr, "Failed to initialize\n" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment