desktop/source/lib/init.cxx | 135 +++++++++++++++++++++------- include/LibreOfficeKit/LibreOfficeKitInit.h | 60 +++++++----- smoketest/libtest.cxx | 24 ++++ 3 files changed, 162 insertions(+), 57 deletions(-)
New commits: commit a320a722439c14b7e6de88fd029e5236032cbda6 Author: Michael Meeks <[email protected]> Date: Tue Aug 18 12:10:05 2015 +0100 Stub initial pre-init phase. Change-Id: I92d172a166606189ce386826eee566623ec4a83c diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 88a2f06..a435b7ef 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -42,6 +42,8 @@ #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/ucb/XContentProvider.hpp> #include <com/sun/star/ucb/XUniversalContentBroker.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> #include <vcl/svapp.hxx> #include <vcl/svpforlokit.hxx> @@ -964,17 +966,69 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit: } } +/// pre-load all C++ component factories and leak references to them. +static void forceLoadAllNativeComponents() +{ + // FIXME: we need to inject RTLD_NOW into here, either by a + // putenv("LD_BIND_NOW=1") in parent process or ... (?). + + try { + uno::Reference<container::XContentEnumerationAccess> xEnumAcc( + xContext->getServiceManager(), css::uno::UNO_QUERY_THROW); + uno::Reference<container::XHierarchicalNameAccess> xTypeMgr( + xContext->getValueByName( + "/singletons/com.sun.star.reflection.theTypeDescriptionManager"), + css::uno::UNO_QUERY_THROW); + uno::Sequence<OUString> aServiceNames( + xContext->getServiceManager()->getAvailableServiceNames()); + + for (sal_Int32 i = 0; i != aServiceNames.getLength(); ++i) + { + css::uno::Reference<css::container::XEnumeration> xServiceImpls( + xEnumAcc->createContentEnumeration(aServiceNames[i]), + css::uno::UNO_SET_THROW); + SAL_INFO("lok", "service " << aServiceNames[i]); + // FIXME: need to actually load and link each native DSO. + } + } catch (const uno::Exception &) { + } +} + +/// pre-load and parse all filter XML +static void forceLoadFilterXML() +{ +} + 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); if (bInitialized) return 1; - comphelper::LibreOfficeKit::setActive(); - comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib); + if (eStage != SECOND_INIT) + comphelper::LibreOfficeKit::setActive(); + if (eStage != PRE_INIT) + comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib); - if (pUserProfilePath) + if (eStage != SECOND_INIT && pUserProfilePath) rtl::Bootstrap::set(OUString("UserInstallation"), OUString(pUserProfilePath, strlen(pUserProfilePath), RTL_TEXTENCODING_UTF8)); OUString aAppPath; @@ -997,22 +1051,30 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char try { - SAL_INFO("lok", "Attempting to initalize UNO"); - if (!initialize_uno(aAppURL)) + if (eStage != SECOND_INIT) { - return false; - } - force_c_locale(); + SAL_INFO("lok", "Attempting to initalize UNO"); - // Force headless -- this is only for bitmap rendering. - rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp"); + if (!initialize_uno(aAppURL)) + return false; + force_c_locale(); - // We specifically need to make sure we have the "headless" - // command arg set (various code specifically checks via - // CommandLineArgs): - desktop::Desktop::GetCommandLineArgs().setHeadless(); + // Force headless -- this is only for bitmap rendering. + rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp"); - Application::EnableHeadlessMode(true); + // We specifically need to make sure we have the "headless" + // command arg set (various code specifically checks via + // CommandLineArgs): + desktop::Desktop::GetCommandLineArgs().setHeadless(); + + Application::EnableHeadlessMode(true); + } + + if (eStage == PRE_INIT) + { + forceLoadAllNativeComponents(); + forceLoadFilterXML(); + } // This is horrible crack. I really would want to go back to simply just call // InitVCL() here. The OfficeIPCThread thing is just horrible. @@ -1033,27 +1095,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 // then use it to wait until we're definitely ready to continue. - SAL_INFO("lok", "Enabling OfficeIPCThread"); - OfficeIPCThread::EnableOfficeIPCThread(); - SAL_INFO("lok", "Starting soffice_main"); - pLib->maThread = osl_createThread(lo_startmain, NULL); - 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()) + if (eStage != PRE_INIT) { - fprintf(stderr, "LOK init failed -- restart required\n"); - return false; + SAL_INFO("lok", "Enabling OfficeIPCThread"); + OfficeIPCThread::EnableOfficeIPCThread(); + SAL_INFO("lok", "Starting soffice_main"); + pLib->maThread = osl_createThread(lo_startmain, NULL); + 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"); - bInitialized = true; + if (eStage == PRE_INIT) + bPreInited = true; + else + bInitialized = true; } catch (css::uno::Exception& exception) { @@ -1088,10 +1157,10 @@ LibreOfficeKit *libreofficekit_hook(const char* install_path) } SAL_JNI_EXPORT -int lok_preinit() +int lok_preinit(const char* install_path, const char* user_profile_path) { SAL_INFO("lok", "Hello World"); - return 0; + return lo_initialize(NULL, install_path, user_profile_path); } static void lo_destroy(LibreOfficeKit* pThis) diff --git a/smoketest/libtest.cxx b/smoketest/libtest.cxx index ae87c79..60ee19e 100644 --- a/smoketest/libtest.cxx +++ b/smoketest/libtest.cxx @@ -83,7 +83,29 @@ int main (int argc, char **argv) return 1; // 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 ) { fprintf( stderr, "Failed to initialize\n" ); commit c35958c5cc8bf637c4911b1251e695234f761a0b Author: Michael Meeks <[email protected]> Date: Tue Aug 18 12:09:08 2015 +0100 lok: namespace and re-work various types & helper functions. Change-Id: I36e2a01822883251f9556fcde0e0a9830356ac98 diff --git a/include/LibreOfficeKit/LibreOfficeKitInit.h b/include/LibreOfficeKit/LibreOfficeKitInit.h index f1966c7..c2f3426 100644 --- a/include/LibreOfficeKit/LibreOfficeKitInit.h +++ b/include/LibreOfficeKit/LibreOfficeKitInit.h @@ -40,7 +40,7 @@ extern "C" #endif #define SEPARATOR '/' - void *_dlopen(const char *pFN) + void *lok_loadlib(const char *pFN) { return dlopen(pFN, RTLD_LAZY #if defined __clang__ && defined __linux__ \ @@ -52,17 +52,17 @@ extern "C" ); } - char *_dlerror(void) + char *lok_dlerror(void) { return dlerror(); } - void *_dlsym(void *Hnd, const char *pName) + void *lok_dlsym(void *Hnd, const char *pName) { return dlsym(Hnd, pName); } - int _dlclose(void *Hnd) + int lok_dlclose(void *Hnd) { return dlclose(Hnd); } @@ -80,24 +80,24 @@ extern "C" #define SEPARATOR '\\' #define UNOPATH "\\..\\URE\\bin" - void *_dlopen(const char *pFN) + void *lok_loadlib(const char *pFN) { return (void *) LoadLibrary(pFN); } - char *_dlerror(void) + char *lok_dlerror(void) { LPSTR buf = NULL; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, reinterpret_cast<LPSTR>(&buf), 0, NULL); return buf; } - void *_dlsym(void *Hnd, const char *pName) + void *lok_dlsym(void *Hnd, const char *pName) { return GetProcAddress((HINSTANCE) Hnd, pName); } - int _dlclose(void *Hnd) + int lok_dlclose(void *Hnd) { return FreeLibrary((HINSTANCE) Hnd); } @@ -139,16 +139,12 @@ extern "C" } #endif -typedef LibreOfficeKit *(HookFunction)( const char *install_path); - -typedef LibreOfficeKit *(HookFunction2)( const char *install_path, const char *user_profile_path ); - -static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_profile_path ) +static void *lok_dlopen( const char *install_path, char ** _imp_lib ) { char *imp_lib; void *dlhandle; - HookFunction *pSym; - HookFunction2 *pSym2; + + *_imp_lib = NULL; #if !(defined(__APPLE__) && defined(__arm__)) size_t partial_length; @@ -172,7 +168,7 @@ static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_p imp_lib[partial_length++] = SEPARATOR; strcpy(imp_lib + partial_length, TARGET_LIB); - dlhandle = _dlopen(imp_lib); + dlhandle = lok_loadlib(imp_lib); if (!dlhandle) { // If TARGET_LIB exists, and likely is a real library (not a @@ -183,18 +179,18 @@ static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_p if (stat(imp_lib, &st) == 0 && st.st_size > 100) { fprintf(stderr, "failed to open library '%s': %s\n", - imp_lib, _dlerror()); + imp_lib, lok_dlerror()); free(imp_lib); return NULL; } strcpy(imp_lib + partial_length, TARGET_MERGED_LIB); - dlhandle = _dlopen(imp_lib); + dlhandle = lok_loadlib(imp_lib); if (!dlhandle) { fprintf(stderr, "failed to open library '%s': %s\n", - imp_lib, _dlerror()); + imp_lib, lok_dlerror()); free(imp_lib); return NULL; } @@ -203,23 +199,41 @@ static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_p imp_lib = strdup("the app executable"); dlhandle = RTLD_MAIN_ONLY; #endif + *_imp_lib = imp_lib; + return dlhandle; +} + +typedef LibreOfficeKit *(LokHookFunction)( const char *install_path); + +typedef LibreOfficeKit *(LokHookFunction2)( const char *install_path, const char *user_profile_path ); + +typedef int (LokHookPreInit) ( const char *install_path, const char *user_profile_path ); + +static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_profile_path ) +{ + char *imp_lib; + void *dlhandle; + LokHookFunction *pSym; + LokHookFunction2 *pSym2; + + dlhandle = lok_dlopen(install_path, &imp_lib); - pSym2 = (HookFunction2 *) _dlsym( dlhandle, "libreofficekit_hook_2" ); + pSym2 = (LokHookFunction2 *) lok_dlsym(dlhandle, "libreofficekit_hook_2"); if (!pSym2) { if (user_profile_path != NULL) { fprintf( stderr, "the LibreOffice version in '%s' does not support passing a user profile to the hook function\n", imp_lib ); - _dlclose( dlhandle ); + lok_dlclose( dlhandle ); free( imp_lib ); return NULL; } - pSym = (HookFunction *) _dlsym( dlhandle, "libreofficekit_hook" ); + pSym = (LokHookFunction *) lok_dlsym( dlhandle, "libreofficekit_hook" ); if (!pSym) { fprintf( stderr, "failed to find hook in library '%s'\n", imp_lib ); - _dlclose( dlhandle ); + lok_dlclose( dlhandle ); free( imp_lib ); return NULL; } _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
