summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/inc/lib/init.hxx4
-rw-r--r--desktop/source/lib/init.cxx55
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.h4
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.hxx15
-rw-r--r--include/sfx2/lokcallback.hxx5
-rw-r--r--include/sfx2/lokhelper.hxx4
-rw-r--r--include/sfx2/viewsh.hxx3
-rw-r--r--include/test/lokcallback.hxx2
-rw-r--r--include/vcl/lok.hxx3
-rw-r--r--sfx2/source/view/lokhelper.cxx25
-rw-r--r--sfx2/source/view/viewsh.cxx7
-rw-r--r--vcl/source/app/svapp.cxx23
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: */