Date: prev next · Thread: first prev next last
2015 Archives by date, by thread · List index


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@collabora.com  <><, Pseudo Engineer, itinerant idiot

Attachment: chase.pl
Description: Perl program


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.