diff options
-rw-r--r-- | desktop/inc/lib/init.hxx | 4 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 55 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.h | 4 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.hxx | 15 | ||||
-rw-r--r-- | include/sfx2/lokcallback.hxx | 5 | ||||
-rw-r--r-- | include/sfx2/lokhelper.hxx | 4 | ||||
-rw-r--r-- | include/sfx2/viewsh.hxx | 3 | ||||
-rw-r--r-- | include/test/lokcallback.hxx | 2 | ||||
-rw-r--r-- | include/vcl/lok.hxx | 3 | ||||
-rw-r--r-- | sfx2/source/view/lokhelper.cxx | 25 | ||||
-rw-r--r-- | sfx2/source/view/viewsh.cxx | 7 | ||||
-rw-r--r-- | vcl/source/app/svapp.cxx | 23 |
12 files changed, 149 insertions, 1 deletions
diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index c5dcea03d9fe..78c74c753063 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -21,6 +21,7 @@ #include <osl/thread.h> #include <rtl/ref.hxx> +#include <rtl/strbuf.hxx> #include <vcl/idle.hxx> #include <LibreOfficeKit/LibreOfficeKit.h> #include <LibreOfficeKit/LibreOfficeKitEnums.h> @@ -117,6 +118,7 @@ namespace desktop { virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart) override; virtual void libreOfficeKitViewUpdatedCallback(int nType) override; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override; + virtual void dumpState(rtl::OStringBuffer &rState) override; private: struct CallbackData @@ -261,6 +263,8 @@ namespace desktop { { return (mOptionalFeatures & feature) != 0; } + + void dumpState(rtl::OStringBuffer &aState); }; /// Helper function to extract the value from parameters delimited by diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index c0f129fef72f..74349ace09a4 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1469,6 +1469,23 @@ void CallbackFlushHandler::libreOfficeKitViewUpdatedCallbackPerViewId(int nType, setUpdatedTypePerViewId(nType, nViewId, nSourceViewId, true); } +void CallbackFlushHandler::dumpState(rtl::OStringBuffer &rState) +{ + // NB. no locking + rState.append("\nView:\t"); + rState.append(static_cast<sal_Int32>(m_viewId)); + rState.append("\n\tDisableCallbacks:\t"); + rState.append(static_cast<sal_Int32>(m_nDisableCallbacks)); + rState.append("\n\tStates:\n"); + for (const auto &i : m_states) + { + rState.append("\n\t\t"); + rState.append(static_cast<sal_Int32>(i.first)); + rState.append("\t"); + rState.append(i.second); + } +} + void CallbackFlushHandler::queue(const int type, const char* data) { CallbackData callbackData(data); @@ -2337,6 +2354,8 @@ static void lo_sendDialogEvent(LibreOfficeKit* pThis, static void lo_setOption(LibreOfficeKit* pThis, const char* pOption, const char* pValue); +static void lo_dumpState(LibreOfficeKit* pThis, const char* pOptions, char** pState); + LibLibreOffice_Impl::LibLibreOffice_Impl() : m_pOfficeClass( gOfficeClass.lock() ) , maThread(nullptr) @@ -2363,6 +2382,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl() m_pOfficeClass->runLoop = lo_runLoop; m_pOfficeClass->sendDialogEvent = lo_sendDialogEvent; m_pOfficeClass->setOption = lo_setOption; + m_pOfficeClass->dumpState = lo_dumpState; gOfficeClass = m_pOfficeClass; } @@ -4159,6 +4179,41 @@ static void lo_setOption(LibreOfficeKit* /*pThis*/, const char *pOption, const c } } +static void lo_dumpState (LibreOfficeKit* pThis, const char* /* pOptions */, char** pState) +{ + if (!pState) + return; + + // NB. no SolarMutexGuard since this may be caused in some extremis / deadlock + SetLastExceptionMsg(); + + *pState = nullptr; + OStringBuffer aState(4096*256); + + LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis); + + pLib->dumpState(aState); + + OString aStr = aState.makeStringAndClear(); + *pState = strdup(aStr.getStr()); +} + +void LibLibreOffice_Impl::dumpState(rtl::OStringBuffer &rState) +{ + rState.append("LibreOfficeKit state:"); + rState.append("\n\tLastExceptionMsg:\t"); + rState.append(rtl::OUStringToOString(maLastExceptionMsg, RTL_TEXTENCODING_UTF8)); + rState.append("\n\tUnipoll:\t"); + rState.append(vcl::lok::isUnipoll() ? "yes" : "no: events on thread"); + rState.append("\n\tOptionalFeatures:\t0x"); + rState.append(static_cast<sal_Int64>(mOptionalFeatures), 16); + rState.append("\n\tCallbackData:\t0x"); + rState.append(reinterpret_cast<sal_Int64>(mpCallback), 16); + // TODO: dump mInteractionMap + SfxLokHelper::dumpState(rState); + vcl::lok::dumpState(rState); +} + static void doc_postUnoCommand(LibreOfficeKitDocument* pThis, const char* pCommand, const char* pArguments, bool bNotifyWhenFinished) { comphelper::ProfileZone aZone("doc_postUnoCommand"); diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index aff71dcc1f5d..3a706ba47091 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -118,6 +118,10 @@ struct _LibreOfficeKitClass /// @see lok::Office::setOption void (*setOption) (LibreOfficeKit* pThis, const char* pOption, const char* pValue); + + /// @see lok::Document::dumpState + /// @since LibreOffice 7.5 + void (*dumpState) (LibreOfficeKit* pThis, const char* pOptions, char** pState); }; #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize) diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index 6dbfbf964b29..4aafaa830626 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -1103,6 +1103,21 @@ public: { mpThis->pClass->setOption(mpThis, pOption, pValue); } + + /** + * Debugging tool for triggering a dump of internal state. + * + * LibreOfficeKit can get into an unhelpful state at run-time when + * in heavy use. This provides a critical tool for inspecting + * relevant internal state. + * + * @param pOption future expansion - string options. + * @param pState - heap allocated, C string containing the state dump. + */ + void dumpState(const char* pOption, char** pState) + { + mpThis->pClass->dumpState(mpThis, pOption, pState); + } }; /// Factory method to create a lok::Office instance. diff --git a/include/sfx2/lokcallback.hxx b/include/sfx2/lokcallback.hxx index 32b6c08f865b..a92f60572145 100644 --- a/include/sfx2/lokcallback.hxx +++ b/include/sfx2/lokcallback.hxx @@ -11,6 +11,10 @@ #include <sal/types.h> +namespace rtl +{ +class OStringBuffer; +} namespace tools { class Rectangle; @@ -46,6 +50,7 @@ public: virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) = 0; + virtual void dumpState(rtl::OStringBuffer& rState) = 0; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 4ac50a19cc69..0b18c0fa7b5e 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -17,6 +17,7 @@ #include <sfx2/viewsh.hxx> #include <tools/gen.hxx> #include <cstddef> +#include <rtl/strbuf.hxx> #include <rtl/string.hxx> #include <optional> #include <string_view> @@ -147,6 +148,9 @@ public: /// This value is chosen such that sal_Int32 will not overflow when manipulated. static const tools::Long MaxTwips = 1e9; + /// Helper for diagnosing run-time problems + static void dumpState(rtl::OStringBuffer &rState); + private: static int createView(SfxViewFrame* pViewFrame, ViewShellDocId docId); }; diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index ea7d966c8cc7..3faf7aeb2071 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -55,6 +55,7 @@ class SfxPrinter; class NotifyEvent; class SfxInPlaceClient; class SfxLokCallbackInterface; +namespace rtl { class OStringBuffer; } namespace vcl { class PrinterController; } namespace com::sun::star::awt{ class XPopupMenu; } @@ -341,6 +342,8 @@ public: /// Set up a more efficient internal callback instead of LibreOfficeKitCallback. void setLibreOfficeKitViewCallback(SfxLokCallbackInterface* pCallback); + /// dump view state for diagnostics + void dumpLibreOfficeKitViewState(rtl::OStringBuffer &rState); /// Invokes the registered callback, if there are any. virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const override; virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) const override; diff --git a/include/test/lokcallback.hxx b/include/test/lokcallback.hxx index a3f383bcec5e..e18724279040 100644 --- a/include/test/lokcallback.hxx +++ b/include/test/lokcallback.hxx @@ -39,6 +39,8 @@ public: virtual void libreOfficeKitViewUpdatedCallback(int nType) override; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override; + virtual void dumpState(rtl::OStringBuffer&) override{}; + virtual void Invoke() override; private: diff --git a/include/vcl/lok.hxx b/include/vcl/lok.hxx index 108f46def8aa..31a4cf1ec494 100644 --- a/include/vcl/lok.hxx +++ b/include/vcl/lok.hxx @@ -12,6 +12,7 @@ #include <sal/config.h> #include <vcl/dllapi.h> +#include <rtl/strbuf.hxx> #include <LibreOfficeKit/LibreOfficeKitTypes.h> namespace vcl::lok @@ -24,6 +25,8 @@ void VCL_DLLPUBLIC unregisterPollCallbacks(); // Called to tell VCL that the number of document views has changed, so that VCL // can adjust e.g. sizes of bitmap caches to scale well with larger number of users. void VCL_DLLPUBLIC numberOfViewsChanged(int count); + +void VCL_DLLPUBLIC dumpState(rtl::OStringBuffer& rState); } #endif // INCLUDE_VCL_LOK_HXX diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 69cbc8b3d131..1d39838bfbf8 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -851,4 +851,29 @@ void SfxLokHelper::postMouseEventAsync(const VclPtr<vcl::Window> &xWindow, LokMo postEventAsync(pLOKEv); } +void SfxLokHelper::dumpState(rtl::OStringBuffer &rState) +{ + SfxViewShell* pShell = SfxViewShell::Current(); + sal_Int32 nDocId = pShell ? static_cast<sal_Int32>(pShell->GetDocId().get()) : -1; + + rState.append("\n\tDocId:\t"); + rState.append(nDocId); + + if (nDocId < 0) + return; + + rState.append("\n\tViewCount:\t"); + rState.append(static_cast<sal_Int32>(getViewsCount(nDocId))); + + const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current(); + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + if (pCurrentViewShell == nullptr || pViewShell->GetDocId() == pCurrentViewShell-> GetDocId()) + pViewShell->dumpLibreOfficeKitViewState(rState); + + pViewShell = SfxViewShell::GetNext(*pViewShell); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index c14b31ce9862..d1f326c68b7f 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -1418,7 +1418,6 @@ bool SfxViewShell::ExecKey_Impl(const KeyEvent& aKey) void SfxViewShell::setLibreOfficeKitViewCallback(SfxLokCallbackInterface* pCallback) { - pImpl->m_pLibreOfficeKitViewCallback = nullptr; pImpl->m_pLibreOfficeKitViewCallback = pCallback; afterCallbackRegistered(); @@ -1436,6 +1435,12 @@ void SfxViewShell::setLibreOfficeKitViewCallback(SfxLokCallbackInterface* pCallb } } +void SfxViewShell::dumpLibreOfficeKitViewState(rtl::OStringBuffer &rState) +{ + if (pImpl->m_pLibreOfficeKitViewCallback) + pImpl->m_pLibreOfficeKitViewCallback->dumpState(rState); +} + static bool ignoreLibreOfficeKitViewCallback(int nType, const SfxViewShell_Impl* pImpl) { if (!comphelper::LibreOfficeKit::isActive()) diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 36beccb6bcb5..0fc4a2b00e36 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -29,6 +29,7 @@ #include <tools/debug.hxx> #include <tools/time.hxx> #include <tools/stream.hxx> +#include <tools/json_writer.hxx> #include <unotools/configmgr.hxx> #include <unotools/resmgr.hxx> @@ -1829,6 +1830,28 @@ void numberOfViewsChanged(int count) rCache.setMaxSize(count * 10); } +void dumpState(rtl::OStringBuffer &rState) +{ + ImplSVData* pSVData = ImplGetSVData(); + if (!pSVData) + return; + + rState.append("\nWindows:\t"); + rState.append(static_cast<sal_Int32>(Application::GetTopWindowCount())); + + vcl::Window *pWin = Application::GetFirstTopLevelWindow(); + while (pWin) + { + tools::JsonWriter props; + pWin->DumpAsPropertyTree(props); + + rState.append("\n\tWindow: "); + rState.append(props.extractAsOString()); + + pWin = Application::GetNextTopLevelWindow( pWin ); + } +} + } // namespace lok, namespace vcl /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |