Bug 216446

Summary: editors/libreoffice: sfx2_classification test crashes during build with clang/libc++ 4.0
Product: Ports & Packages Reporter: Jan Beich <jbeich>
Component: Individual Port(s)Assignee: FreeBSD Office Team <office>
Status: Closed Unable to Reproduce    
Severity: Affects Only Me CC: dim, office
Priority: --- Flags: bugzilla: maintainer-feedback? (office)
Version: Latest   
Hardware: Any   
OS: Any   
Bug Depends on:    
Bug Blocks: 216008    
Attachments:
Description Flags
VALGRIND=memcheck (from a regular build)
none
VALGRIND=memcheck (-O1 -g build)
none
Fix libreoffice's sfx2_classification unit test none

Description Jan Beich freebsd_committer freebsd_triage 2017-01-24 19:03:42 UTC
I've been testing /projects/clang400-import on drm-next kernel for a week both on i386 and amd64 but the following issue failed to disappear.

$ make
[...]
[build SLC] sc
[build CUT] sw_docbookexport
[build CUT] sw_htmlimport
Segmentation fault

No core file identified in directory /wrkdirs/usr/ports/editors/libreoffice/work/libreoffice-5.2.4.2/workdir/CppunitTest/sfx2_classification.test.core
To show backtraces for crashes during test execution,
enable core files with:

   ulimit -c unlimited


Error: a unit test failed, please do one of:
make CppunitTest_sfx2_classification CPPUNITTRACE="gdb --args"
    # for interactive debugging on Linux
make CppunitTest_sfx2_classification VALGRIND=memcheck
    # for memory checking
make CppunitTest_sfx2_classification DEBUGCPPUNIT=TRUE
    # for exception catching

$ make ALL_TARGET=CppunitTest_sfx2_classification CPPUNITTRACE="lldb --"
[...]
(lldb) r
Process 84656 launching
Process 84656 launched: '/wrkdirs/usr/ports/editors/libreoffice/work/libreoffice-5.2.4.2/workdir/LinkTarget/Executable/cppunittester' (x86_64)
Process 84656 stopped
* thread #1, stop reason = signal SIGSEGV: invalid address (fault address: 0xc0000171)
    frame #0: 0x0000000815174225 libsfxlo.so`SfxClassificationHelper::Impl::pushToDocumentProperties(void) + 37
libsfxlo.so`SfxClassificationHelper::Impl::pushToDocumentProperties:
->  0x815174225 <+37>: callq  *0x170(%rax)
    0x81517422b <+43>: movq   -0x48(%rbp), %rbx
    0x81517422f <+47>: xorl   %edi, %edi
    0x815174231 <+49>: callq  0x814f31ec0               ; com::sun::star::beans::cppu_detail_getUnoType(com::sun::star::beans::XPropertySet const*)
(lldb) bt
* thread #1, stop reason = signal SIGSEGV: invalid address (fault address: 0xc0000171)
  * frame #0: 0x0000000815174225 libsfxlo.so`SfxClassificationHelper::Impl::pushToDocumentProperties(void) + 37
    frame #1: 0x0000000815177ab3 libsfxlo.so`SfxClassificationHelper::SetBACName(rtl::OUString const&, SfxClassificationPolicyType) + 579
    frame #2: 0x00000008192a2a1b libswlo.so`SwEditShell::SetClassification(rtl::OUString const&, SfxClassificationPolicyType) + 155
    frame #3: 0x000000081977e678 libswlo.so`SwDocShell::Execute(SfxRequest&) + 5864
    frame #4: 0x000000081983ec39 libswlo.so`SwBaseShell::Execute(SfxRequest&) + 2505
    frame #5: 0x0000000814fa3618 libsfxlo.so`SfxDispatcher::Call_Impl(SfxShell&, SfxSlot const&, SfxRequest&, bool) + 696
    frame #6: 0x0000000814fa5596 libsfxlo.so`SfxDispatcher::Execute(unsigned short, SfxCallMode, SfxItemSet*, SfxItemSet, unsigned short) + 422
    frame #7: 0x0000000814fdd7cd libsfxlo.so`SfxDispatchController_Impl::dispatch(com::sun::star::util::URL const&, com::sun::uno::Sequence<com::sun::beans::PropertyValue> const&, com::sun::star::util::URL const&::Reference<com::sun::frame::XDispatchResultListener> const&) + 3997
    frame #8: 0x0000000814fde002 libsfxlo.so`virtual function non-virtual override offset : -40 SfxOfficeDispatch::dispatchWithNotification(com::sun::star::util::URL const&, com::sun::uno::Sequence<com::sun::beans::PropertyValue> const&, com::sun::star::util::URL const&::Reference<com::sun::frame::XDispatchResultListener> const&) + 18
    frame #9: 0x00000008212aea31 libfwllo.so`framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::frame::XDispatchProvider> const&, rtl::OUString const&, rtl::OUString const, int, com::sun::star::Sequence<com::sun::beans::PropertyValue> const&) + 1361
    frame #10: 0x00000008212aeeca libfwllo.so`virtual function non-virtual override offset : -48 framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::frame::XDispatchProvider> const&, rtl::OUString const&, rtl::OUString const, int, com::sun::star::Sequence<com::sun::beans::PropertyValue> const&) + 26
    frame #11: 0x0000000814607d52 libtest_sfx2_classification.so`(anonymous namespace)::ClassificationTest::dispatchCommand(com::sun::star::uno::Reference<com::sun::lang::XComponent> const&, rtl::OUString const&, com::sun::star::Sequence<com::sun::beans::PropertyValue> const&) + 1522
    frame #12: 0x0000000814606400 libtest_sfx2_classification.so`(anonymous namespace)::ClassificationTest::testClassification(void) + 480
    frame #13: 0x000000081460573a libtest_sfx2_classification.so`(anonymous namespace)::ClassificationTest::testWriter(void) + 794
    frame #14: 0x0000000800856a02 libcppunit-1.13.so.0`CppUnit::TestCaseMethodFunctor::operator()(void) const + 34
    frame #15: 0x0000000802001283 unoexceptionprotector.so`(anonymous namespace)::Prot::protect(CppUnit::Functor const&, (anonymous namespace)::Prot::protect::ProtectorContext const&) + 35
    frame #16: 0x00000008008498e3 libcppunit-1.13.so.0`CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) + 35
    frame #17: 0x000000080085274b libcppunit-1.13.so.0`CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) + 363
    frame #18: 0x000000080085df06 libcppunit-1.13.so.0`CppUnit::TestResult::protect(CppUnit::Functorconst&, CppUnit::Test*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 54
    frame #19: 0x00000008008566f3 libcppunit-1.13.so.0`CppUnit::TestCase::run(CppUnit::TestResult*) + 227
    frame #20: 0x0000000800856ef5 libcppunit-1.13.so.0`CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) + 85
    frame #21: 0x0000000800856ddf libcppunit-1.13.so.0`CppUnit::TestComposite::run(CppUnit::TestResult*) + 31
    frame #22: 0x0000000800856ef5 libcppunit-1.13.so.0`CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) + 85
    frame #23: 0x0000000800856ddf libcppunit-1.13.so.0`CppUnit::TestComposite::run(CppUnit::TestResult*) + 31
    frame #24: 0x000000080085dcb2 libcppunit-1.13.so.0`CppUnit::TestResult::runTest(CppUnit::Test*) + 34
    frame #25: 0x0000000800860ed3 libcppunit-1.13.so.0`CppUnit::TestRunner::run(CppUnit::TestResult&, std::__1::basic_string<char, CppUnit::TestResult&::char_traits<char>, CppUnit::TestResult&::allocator<char> > const&) + 51
    frame #26: 0x0000000000405385 cppunittester`(anonymous namespace)::ProtectedFixtureFunctor::run(void) const + 853
    frame #27: 0x0000000000404463 cppunittester`main + 1011
    frame #28: 0x0000000000403f6f cppunittester`_start + 383
Comment 1 Dimitry Andric freebsd_committer freebsd_triage 2017-01-24 19:11:23 UTC
Sigh, I always have great difficulty getting libreoffice built with sensible debug information, and also the humongous build system doesn't really help. :)

Can you run the test under valgrind, e.g. according to its suggestion:

make CppunitTest_sfx2_classification VALGRIND=memcheck

?

That said, the previous libreoffice crash I saw occurred *only* during its main build process.  Running it with an invocation like above never crashed. :(
Comment 2 Jan Beich freebsd_committer freebsd_triage 2017-01-24 19:26:48 UTC
Created attachment 179289 [details]
VALGRIND=memcheck (from a regular build)

May not be very useful unless built with -O0 -g.
Comment 3 Dimitry Andric freebsd_committer freebsd_triage 2017-01-24 20:07:17 UTC
Oh but the crash also occurs on amd64? There it is at least feasible to build with debuginfo.  On i386, this almost never completes successfully, because there isn't enough memory for it.
Comment 4 Jan Beich freebsd_committer freebsd_triage 2017-01-24 21:03:31 UTC
My build using the following settings didn't crash.

  $ cat Makefile.local
  CFLAGS += -O0 -g
  STRIP=
  SSP_CFLAGS=
Comment 5 Jan Beich freebsd_committer freebsd_triage 2017-01-25 00:06:31 UTC
Created attachment 179294 [details]
VALGRIND=memcheck (-O1 -g build)

comment 0 with -O1 -g:

(lldb) r
Process 86275 launching
Process 86275 launched: '/wrkdirs/usr/ports/editors/libreoffice/work/libreoffice-5.2.4.2/workdir/LinkTarget/Executable/cppunittester' (x86_64)
Process 86275 stopped
* thread #1, stop reason = signal SIGSEGV: invalid address (fault address: 0xc0000171)
    frame #0: libsfxlo.so`SfxClassificationHelper::Impl::pushToDocumentProperties(this=0x00000008204ccb80) at classificationhelper.cxx:422
   419
   420  void SfxClassificationHelper::Impl::pushToDocumentProperties()
   421  {
-> 422      uno::Reference<beans::XPropertyContainer> xPropertyContainer = m_xDocumentProperties->getUserDefinedProperties();
   423      uno::Reference<beans::XPropertySet> xPropertySet(xPropertyContainer, uno::UNO_QUERY);
   424      uno::Sequence<beans::Property> aProperties = xPropertySet->getPropertySetInfo()->getProperties();
   425      for (auto& rPair : m_aCategory)
(lldb) p m_xDocumentProperties
(const com::sun::star::uno::Reference<com::sun::star::document::XDocumentProperties>) $0 = {
  com::sun::star::uno::BaseReference = (_pInterface = 0x0000000800b448b8)
}
(lldb) fr v
(SfxClassificationHelper::Impl *) this = 0x00000008204ccb80
(com::sun::star::uno::Reference<com::sun::star::beans::XPropertyContainer>) xPropertyContainer = {
  com::sun::star::uno::BaseReference = (_pInterface = 0x07e1000100190000)
}
(com::sun::star::uno::Sequence<com::sun::star::beans::Property>) aProperties = <variable not available>

(com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>) xPropertySet = <variable not available>

(lldb) bt
* thread #1, stop reason = signal SIGSEGV: invalid address (fault address: 0xc0000171)
  * frame #0: libsfxlo.so`SfxClassificationHelper::Impl::pushToDocumentProperties(this=0x00000008204ccb80) at classificationhelper.cxx:422
    frame #1: libsfxlo.so`SfxClassificationHelper::SetBACName(this=<unavailable>, rName=<unavailable>, eType=<unavailable>) at classificationhelper.cxx:772
    frame #2: libswlo.so`SwEditShell::SetClassification(this=<unavailable>, rName=0x000000082048bbb8, eType=ExportControl) at edfcol.cxx:185
    frame #3: libswlo.so`SwDocShell::Execute(this=0x0000000814b648a0, rReq=0x00007fffffff2490) at docsh2.cxx:1155
    frame #4: libswlo.so`SwBaseShell::Execute(this=0x00000008204b8a00, rReq=0x00007fffffff2490) at basesh.cxx:918
    frame #5: libsfxlo.so`SfxDispatcher::Call_Impl(this=0x000000081f26bd40, rShell=<unavailable>, rSlot=<unavailable>, rReq=<unavailable>, bRecord=<unavailable>) at dispatch.cxx:362
    frame #6: libsfxlo.so`SfxDispatcher::Execute(this=0x000000081f26bd40, nSlot=<unavailable>, nCall=<unavailable>, pArgs=<unavailable>, pInternalArgs=0x00007fffffff2658, nModi=0) at dispatch.cxx:1017
    frame #7: libsfxlo.so`SfxDispatchController_Impl::dispatch(this=<unavailable>, aURL=<unavailable>, aArgs=<unavailable>, rListener=0x00007fffffff2768) at unoctitm.cxx:704
    frame #8: libsfxlo.so`SfxOfficeDispatch::dispatchWithNotification(this=<unavailable>, aURL=<unavailable>, aArgs=<unavailable>, rListener=<unavailable>) at unoctitm.cxx:224
    frame #9: libfwllo.so`framework::DispatchHelper::executeDispatch(this=<unavailable>, xDispatchProvider=0x00007fffffff28a8, sURL=<unavailable>, sTargetFrameName=0x00007fffffff2908, nSearchFlags=0, lArguments=<unavailable>) at dispatchhelper.cxx:131
    frame #10: libfwllo.so`virtual function non-virtual override offset : -48 framework::DispatchHelper::executeDispatch(this=<unavailable>, xDispatchProvider=<unavailable>, sURL=<unavailable>, sTargetFrameName=<unavailable>, nSearchFlags=<unavailable>, lArguments=0x00007fffffff2a48) at dispatchhelper.cxx:0
    frame #11: libtest_sfx2_classification.so`(anonymous namespace)::ClassificationTest::dispatchCommand(this=<unavailable>, xComponent=<unavailable>, rCommand=<unavailable>, rPropertyValues=<unavailable>) at test_classification.cxx:75
    frame #12: libtest_sfx2_classification.so`(anonymous namespace)::ClassificationTest::testClassification(this=<unavailable>) at test_classification.cxx:85
    frame #13: libtest_sfx2_classification.so`(anonymous namespace)::ClassificationTest::testWriter(this=0x000000081498b3a0) at test_classification.cxx:119
    frame #14: libcppunit-1.13.so.0`CppUnit::TestCaseMethodFunctor::operator(this=0x00007fffffff3ca8)(void) const at TestCase.cpp:32
    frame #15: libcppunit-1.13.so.0`CppUnit::ProtectorChain::ProtectFunctor::operator(this=0x00000008149e8d80)(void) const at ProtectorChain.cpp:20
    frame #16: libcppunit-1.13.so.0`CppUnit::ProtectorChain::ProtectFunctor::operator(this=0x00000008149e8d60)(void) const at ProtectorChain.cpp:20
    frame #17: unoexceptionprotector.so`(anonymous namespace)::Prot::protect(this=0x000000080224a018, functor=<unavailable>, context=0x00007fffffff3aa8)::Prot::protect::ProtectorContext const&) at unoexceptionprotector.cxx:65
    frame #18: libcppunit-1.13.so.0`CppUnit::ProtectorChain::ProtectFunctor::operator(this=0x00000008149e8e00)(void) const at ProtectorChain.cpp:20
    frame #19: libcppunit-1.13.so.0`CppUnit::DefaultProtector::protect(this=0x000000080224a008, functor=0x00000008149e8e00, context=0x00007fffffff3aa8) at DefaultProtector.cpp:15
    frame #20: libcppunit-1.13.so.0`CppUnit::ProtectorChain::ProtectFunctor::operator(this=0x00000008149e8da0)(void) const at ProtectorChain.cpp:20
    frame #21: libcppunit-1.13.so.0`CppUnit::ProtectorChain::protect(this=0x000000080221b100, functor=0x00007fffffff3ca8, context=0x00007fffffff3aa8) at ProtectorChain.cpp:77
    frame #22: libcppunit-1.13.so.0`CppUnit::TestResult::protect(this=0x00007fffffff4710, functor=0x00007fffffff3ca8, test=0x00000008149a6b30, shortDescription=0x00007fffffff3c80) at TestResult.cpp:181
    frame #23: libcppunit-1.13.so.0`CppUnit::TestCase::run(this=0x00000008149a6b30, result=0x00007fffffff4710) at TestCase.cpp:91
    frame #24: libcppunit-1.13.so.0`CppUnit::TestComposite::doRunChildTests(this=0x00000008149e7980,controller=0x00007fffffff4710) at TestComposite.cpp:64
    frame #25: libcppunit-1.13.so.0`CppUnit::TestComposite::run(this=0x00000008149e7980, result=0x00007fffffff4710) at TestComposite.cpp:23
    frame #26: libcppunit-1.13.so.0`CppUnit::TestComposite::doRunChildTests(this=0x00000008149e7940,controller=0x00007fffffff4710) at TestComposite.cpp:64
    frame #27: libcppunit-1.13.so.0`CppUnit::TestComposite::run(this=0x00000008149e7940, result=0x00007fffffff4710) at TestComposite.cpp:23
    frame #28: libcppunit-1.13.so.0`CppUnit::TestRunner::WrappingSuite::run(this=0x00000008149e7900,result=0x00007fffffff4710) at TestRunner.cpp:47
    frame #29: libcppunit-1.13.so.0`CppUnit::TestResult::runTest(this=0x00007fffffff4710, test=0x00000008149e7900) at TestResult.cpp:148
    frame #30: libcppunit-1.13.so.0`CppUnit::TestRunner::run(this=0x00007fffffff4490, controller=0x00007fffffff4710, testPath=0x00007fffffff4510) at TestRunner.cpp:96
    frame #31: cppunittester`(anonymous namespace)::ProtectedFixtureFunctor::run(this=0x00007fffffff4638) const at cppunittester.cxx:305
    frame #32: cppunittester`sal_main(void) at cppunittester.cxx:455
    frame #33: cppunittester`main(argc=<unavailable>, argv=<unavailable>) at cppunittester.cxx:362
    frame #34: 0x000000000040451f cppunittester`_start + 383
Comment 6 Dimitry Andric freebsd_committer freebsd_triage 2017-01-28 16:23:31 UTC
I can reproduce it here.  It looks like xDocumentProperties (a member of SfxClassificationHelper::Impl) is simply not initialized properly:

(gdb) print m_xDocumentProperties._pInterface
$17 = (com::sun::star::uno::XInterface *) 0x800abed48 <aImplEmpty_rtl_uString>

E.g. it is a reference to some common "empty string" instance, while it looks like it is supposed to be of type css::uno::Reference< css::document::XDocumentProperties > instead.

It is initialized in SwEditShell::SetClassification() like this:

void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPolicyType eType)
{
    SwDocShell* pDocShell = GetDoc()->GetDocShell();
    if (!pDocShell)
        return;

    SfxClassificationHelper aHelper(pDocShell->getDocProperties());

So for some reason, pDocShell->getDocProperties() is returning this "empty string" value.

I'm putting office@ on CC, maybe somebody who knows LibreOffice has an idea what is going wrong here?  My assumption is that pDocShell is not initialized properly yet, or some initialization order fiasco is going on.
Comment 7 Dimitry Andric freebsd_committer freebsd_triage 2017-01-29 00:59:24 UTC
Created attachment 179388 [details]
Fix libreoffice's sfx2_classification unit test

Here is a patch that fixes the sfx2_classification unit test, at least for me. The resulting libreoffice installs and runs OK, at least with some light testing.

I am not completely sure why this fix works though.  My suspicion is that the reference returned from pDocShell->getDocProperties() is a temporary object, which gets passed to a SfxClassificationHelper object, but it is destroyed or invalidated before it is being accessed in SfxClassificationHelper.  By storing the return value from pDocShell->getDocProperties() in a local object, the destruction or invalidation is postponed to the end of the SwEditShell::SetClassification() function.

There are a few other places in the source where this pattern is repeated, in some cases storing the getDocProperties() result in a local object, in other cases directly passing it to another constructor, so there is not much consistency.

Somebody who understands libreoffice's class structure and object reference mechanism better should attempt to explain this more coherently.  Until that moment, this patch seems to do the trick...
Comment 8 Dimitry Andric freebsd_committer freebsd_triage 2017-02-04 20:59:25 UTC
So, did anybody attempt to use my patch?  I would like to get this fix in, since it causes the most skipped ports for bug 216008 (though most of those are libreoffice language packs, it seems :).