diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-08-10 10:39:59 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-08-16 10:41:56 +0200 |
commit | bc9a2ba677ce3fcd46c2bbef6e8faeacb14292c1 (patch) | |
tree | 49a79f270e5ac924c18602c7ee6631cd07ab918a /sal | |
parent | 747a38a77df7b9d1365670d32d604c2fa69e869f (diff) |
assert on duplicate listener in SfxListener
To enable finding the source of the duplicate calls, I add new SAL
API (only for internal use) to retrieve and symbolise stack
backtraces.
The theory is that it relatively cheap to just store a backtrace,
but quite expense to symbolise it to strings. Note that the
backtrace() library we use on Linux does not do a particularly
good job, but it gives enough information that developers can use
the addr2line tool to get more precise info.
Explanation of fixes in the code that triggered the assert:
In SwFrameHolder, we need to only call StartListening() if the
pFrame member is actually changing. We also need to call
EndListening() on the old values when pFrame changes.
In SwNavigationPI, there is already a StartListening() call in
the only place we assign to m_pCreateView.
In ImpEditEngine, we need to ignore duplicates, because it is
doing a ref-counting thing. By storing duplicates on the listener
list, it doesn't need to keep track of which stylesheets its
child nodes are using. Given that it therefore will see
duplicate events, there is probably some performance optimisation
opportunities here.
In MasterPageObserver::Implementation::RegisterDocument, we
seem to be getting called multiple times with the same
SdDrawDocument, so just check if we've been registered already
before calling StartListening()
In SvxShape::impl_initFromSdrObject, do the same thing we do
elsewhere in this class, i.e. only call StartListening()
if the model has changed.
Change-Id: I7eae5c774e1e8d56f0ad7bec80e4df0017b287ac
Reviewed-on: https://gerrit.libreoffice.org/41045
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'sal')
-rw-r--r-- | sal/osl/unx/backtraceapi.cxx | 30 | ||||
-rw-r--r-- | sal/osl/w32/backtrace.cxx | 51 | ||||
-rw-r--r-- | sal/util/sal.map | 6 |
3 files changed, 87 insertions, 0 deletions
diff --git a/sal/osl/unx/backtraceapi.cxx b/sal/osl/unx/backtraceapi.cxx index 91be8d5d40c4..4838474be36c 100644 --- a/sal/osl/unx/backtraceapi.cxx +++ b/sal/osl/unx/backtraceapi.cxx @@ -18,6 +18,7 @@ #include <rtl/ustrbuf.hxx> #include <rtl/ustring.hxx> #include <sal/types.h> +#include <sal/backtrace.hxx> #include "backtrace.h" #include "backtraceasstring.hxx" @@ -58,4 +59,33 @@ OUString osl::detail::backtraceAsString(sal_uInt32 maxDepth) { return b3.makeStringAndClear(); } +std::unique_ptr<BacktraceState> sal_backtrace_get(sal_uInt32 maxDepth) +{ + assert(maxDepth != 0); + auto const maxInt = static_cast<unsigned int>( + std::numeric_limits<int>::max()); + if (maxDepth > maxInt) { + maxDepth = static_cast<sal_uInt32>(maxInt); + } + auto b1 = new void *[maxDepth]; + int n = backtrace(b1, static_cast<int>(maxDepth)); + return std::unique_ptr<BacktraceState>(new BacktraceState{ b1, n }); +} + +OUString sal_backtrace_to_string(BacktraceState* backtraceState) +{ + FreeGuard b2(backtrace_symbols(backtraceState->buffer, backtraceState->nDepth)); + if (b2.buffer == nullptr) { + return OUString(); + } + OUStringBuffer b3; + for (int i = 0; i != backtraceState->nDepth; ++i) { + if (i != 0) { + b3.append("\n"); + } + b3.append(o3tl::runtimeToOUString(b2.buffer[i])); + } + return b3.makeStringAndClear(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/w32/backtrace.cxx b/sal/osl/w32/backtrace.cxx index a8a4cf445e9f..230adca4a2f8 100644 --- a/sal/osl/w32/backtrace.cxx +++ b/sal/osl/w32/backtrace.cxx @@ -19,6 +19,7 @@ #include <DbgHelp.h> #include <rtl/ustrbuf.hxx> +#include <sal/backtrace.hxx> #include "backtraceasstring.hxx" @@ -64,4 +65,54 @@ OUString osl::detail::backtraceAsString(sal_uInt32 maxDepth) return aBuf.makeStringAndClear(); } +std::unique_ptr<BacktraceState> sal_backtrace_get(sal_uInt32 maxDepth) +{ + assert(maxDepth != 0); + auto const maxUlong = std::numeric_limits<ULONG>::max(); + if (maxDepth > maxUlong) { + maxDepth = static_cast<sal_uInt32>(maxUlong); + } + + HANDLE hProcess = GetCurrentProcess(); + SymInitialize( hProcess, nullptr, true ); + + auto pStack = new void *[maxDepth]; + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633.aspx + // "CaptureStackBackTrace function" claims that you "can capture up to + // MAXUSHORT frames", and on Windows Server 2003 and Windows XP it even + // "must be less than 63", but assume that a too large input value is + // clamped internally, instead of resulting in an error: + int nFrames = CaptureStackBackTrace( 0, static_cast<ULONG>(maxDepth), pStack, nullptr ); + + return std::unique_ptr<BacktraceState>(new BacktraceState{ pStack, nFrames }); +} + +OUString sal_backtrace_to_string(BacktraceState* backtraceState) +{ + OUStringBuffer aBuf; + + SYMBOL_INFO * pSymbol; + pSymbol = static_cast<SYMBOL_INFO *>(calloc( sizeof( SYMBOL_INFO ) + 1024 * sizeof( char ), 1 )); + pSymbol->MaxNameLen = 1024 - 1; + pSymbol->SizeOfStruct = sizeof( SYMBOL_INFO ); + HANDLE hProcess = GetCurrentProcess(); + + auto nFrames = backtraceState->nDepth; + for( int i = 0; i < nFrames; i++ ) + { + SymFromAddr( hProcess, reinterpret_cast<DWORD64>(backtraceState->buffer[ i ]), nullptr, pSymbol ); + aBuf.append( (sal_Int32)(nFrames - i - 1) ); + aBuf.append( ": " ); + aBuf.appendAscii( pSymbol->Name ); + aBuf.append( " - 0x" ); + aBuf.append( (sal_Int64)pSymbol->Address, 16 ); + aBuf.append( "\n" ); + } + + free( pSymbol ); + + return aBuf.makeStringAndClear(); +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/util/sal.map b/sal/util/sal.map index b04487e4d548..e9195a1434f8 100644 --- a/sal/util/sal.map +++ b/sal/util/sal.map @@ -733,6 +733,12 @@ PRIVATE_1.3 { # LibreOffice 5.4 sal_detail_log_report; } PRIVATE_1.2; +PRIVATE_1.4 { # LibreOffice 6.0 + global: + _Z17sal_backtrace_getj; + _Z23sal_backtrace_to_stringP14BacktraceState; +} PRIVATE_1.3; + PRIVATE_textenc.1 { # LibreOffice 3.6 global: _ZN3sal6detail7textenc20convertCharToUnicode*; |