tool for chasing elusive VclPtr<> crashers ...
Michael Meeks
michael.meeks at collabora.com
Wed May 13 04:00:29 PDT 2015
Hi guys,
I've been chasing this bug:
https://bugs.documentfoundation.org/show_bug.cgi?id=91125
on and off for around a week. And it's quite an amazing one =)
Before I go further, I'd like to hope this is quite a rare specimen -
the vast majority of VclPtr<> bugs are really not this bug; so this is
really a thing of last-resort:
The stack trace shows something like this:
0x4C28FAC: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
0x3134D719: ScPivotLayoutTreeListLabel::~ScPivotLayoutTreeListLabel() (PivotLayoutTreeListLabel.cxx:33)
Here we delete this guy - which sounds sensible; except that ...
0xB7F3FC4: OutputDevice::release() const (outdev.hxx:284)
0xB7F71FB: rtl::Reference<vcl::Window>::set(vcl::Window*) (ref.hxx:95)
0xB7F5249: rtl::Reference<vcl::Window>::operator=(rtl::Reference<vcl::Window> const&) (ref.hxx:106)
0xB7F4214: VclPtr<vcl::Window>::operator=(VclPtr<vcl::Window> const&) (vclptr.hxx:83)
0xB82AFF4: vcl::Window::ImplRemoveWindow(bool) (stacking.cxx:148)
0xB9A8E20: vcl::Window::dispose() (window.cxx:511)
0xBA12D1D: Control::dispose() (ctrl.cxx:76)
0x9B434A5: SvTreeListBox::dispose() (treelistbox.cxx:1584)
0x313499FD: ScPivotLayoutTreeListBase::dispose() (PivotLayoutTreeListBase.cxx:38)
0xBAEF813: OutputDevice::disposeOnce() (outdev.cxx:203)
0xB85E3BF: VclPtr<vcl::Window>::disposeAndClear() (vclptr.hxx:209)
In this frame we are holding a reference (to ensure that the object
lives until the end of the disposeAndClear)
0xB83F000: VclBuilder::disposeBuilder() (builder.cxx:536)
So - despite all the smart-ref-counting logic - somehow we're getting
the reference counting wrong:
So ... after about a week of chasing this on & off, I found the bug
which is here:
sal_Int8 SvTreeListBox::ExecuteDrop( const ExecuteDropEvent& rEvt, SvTreeListBox* pSourceView )
...
SvLBoxDDInfo aDDInfo;
memset( &aDDInfo, 0, sizeof(SvLBoxDDInfo) );
TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
if( aData.HasFormat( SotClipboardFormatId::TREELISTBOX ))
{
css::uno::Sequence<sal_Int8> aSeq = aData.GetSequence(SotClipboardFormatId::TREELISTBOX, OUString());
if (sizeof(SvLBoxDDInfo) == aSeq.getLength())
{
memcpy( &aDDInfo, aSeq.getConstArray(), sizeof(SvLBoxDDInfo) );
This final memcpy writes over a VclPtr<> inside the aDDInfo struct:
struct SvLBoxDDInfo
{
Application* pApp;
VclPtr<SvTreeListBox> pSource;
...
Lets hold our breath and gloss over the -horrible- details of passing
raw pointers through an UNO sequence as a byte array and then ... [ it
seems the D&D code - which is also threaded ] is some living nightmare
in this regard ;-)
Anyhow - the question is: how to find this stuff ? the problem being
that when you track every one of the (2000+) acquire/releases on the
underlying ref-count they all appear to be correct: there are just more
releases than there should be. [ the ref-count is stored in the object
not the VclPtr which is clobbered ].
Anyhow - here is how:
a) run soffice.bin under gdb:
gdb --args ./soffice.bin 2>&1 | tee /tmp/gdb-log.txt
place a breakpoint in the 'makeFoo' function you're
interested in - it is rather useful to get this function
before the construction really gets going.
(gdb) print &mnRefCnt
$1 = (int *) 0x12345678
(gdb) watch *$1
This creates a hardware watch-point so whenever the ref-count
changes you get a trace.
(gdb) set pagination off
(gdb) continue
<it will break shortly afterwards>
(gdb) commands
backtrace 10
continue
end
(gdb) continue
This will then produce a log of all stack frames that maniplate the
'mnRefCnt' - in my case this produced 2000+ of them or so ;-)
It is probable that you want a dbgutil build - or at least one with
no-optimization too.
When you hit your crash quit gdb.
You should have a nice gdb-log.txt now.
now
$ cat gdb-log.txt | chase.pl
Problematic ref-count mis-matches on VclPtr instances with values:
this=0x7fffd7391148 -1
this=0x7fffffff6e70 -1
this=0x7fffffffc5b0 1
Search for the above pointer values in your log.
Then look for the above ptr values in your log eg.
Old value = 22
New value = 21
0x00007ffff2af3647 in OutputDevice::release (this=0x2252e10) at /data/opt/libreoffice/master/include/vcl/outdev.hxx:284
284 if (!--mnRefCnt)
#0 0x00007ffff2af3647 in OutputDevice::release (this=0x2252e10) at /data/opt/libreoffice/master/include/vcl/outdev.hxx:284
#1 0x00007ffff2baa6bb in rtl::Reference<SvTreeListBox>::~Reference (this=0x7fffd7391148, __in_chrg=<optimized out>) at /data/opt/libreoffice/master/include/rtl/ref.hxx:81
#2 0x00007ffff2ba9eca in VclPtr<SvTreeListBox>::~VclPtr (this=0x7fffd7391148, __in_chrg=<optimized out>) at /data/opt/libreoffice/master/include/vcl/vclptr.hxx:83
******* ^^^^^^^^^^^^^^ matching mis-counted VclPtr 'this'
#3 0x00007ffff2bdf75e in SvLBoxDDInfo::~SvLBoxDDInfo (this=0x7fffd7391140, __in_chrg=<optimized out>) at /data/opt/libreoffice/master/include/svtools/treelistbox.hxx:820
#4 0x00007ffff2bd4fdd in SvTreeListBox::ExecuteDrop (this=0x222eda0, rEvt=..., pSourceView=0x2252e10) at /data/opt/libreoffice/master/svtools/source/contnr/treelistbox.cxx:1282
And this of course took me straight to the SvLBoxDDInfo code.
Phew ;-)
I hope that's never useful for someone else =)
ATB,
Michael.
--
michael.meeks at collabora.com <><, Pseudo Engineer, itinerant idiot
-------------- next part --------------
A non-text attachment was scrubbed...
Name: chase.pl
Type: application/x-perl
Size: 1334 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/libreoffice/attachments/20150513/ee3f05f3/attachment.bin>
More information about the LibreOffice
mailing list