diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2023-02-01 11:29:14 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2023-02-01 13:45:03 +0000 |
commit | 51a2e1a3963aae3228c9ddf78d0039c7c063393c (patch) | |
tree | fb159bc7ca75c19158bce8ea5a654925f7ceeed4 /vcl | |
parent | 60bc7d7acd9c6656b3124b2015ab26f26b47cb32 (diff) |
Let executeAction always ProcessEventsToIdle
An ASan UITest_writer_tests7
UITEST_TEST_NAME=tdf135938.tdf135938.test_tdf135938_cross_reference_update
occasionally failed for me with
> ==1994973==ERROR: AddressSanitizer: heap-use-after-free on address 0x60f00014d718 at pc 0x7f95f4946ffa bp 0x7f95907fd720 sp 0x7f95907fd718
> READ of size 8 at 0x60f00014d718 thread T33
> #0 in std::__cxx1998::vector<std::unique_ptr<SvLBoxItem, std::default_delete<SvLBoxItem>>, std::allocator<std::unique_ptr<SvLBoxItem, std::default_delete<SvLBoxItem>>>>::size() const at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_vector.h:988:40
> #1 in SvTreeListEntry::ItemCount() const at vcl/source/treelist/treelistentry.cxx:110:20
> #2 in SvTabListBox::GetEntryText(SvTreeListEntry const*, unsigned short) at vcl/source/treelist/svtabbx.cxx:289:37
> #3 in SvTabListBox::GetEntryText(SvTreeListEntry*) const at vcl/source/treelist/svtabbx.cxx:280:12
> #4 in TreeListEntryUIObject::get_state() at vcl/source/treelist/uiobject.cxx:119:32
> #5 in UIObjectUnoObj::getState() at vcl/source/uitest/uno/uiobject_uno.cxx:164:29
> #6 in non-virtual thunk to UIObjectUnoObj::getState() at vcl/source/uitest/uno/uiobject_uno.cxx
> #7 in gcc3::callVirtualMethod(void*, unsigned int, void*, _typelib_TypeDescriptionReference*, bool, unsigned long*, unsigned int, unsigned long*, double*) at bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:77:5
> #8 in cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy*, bridges::cpp_uno::shared::VtableSlot, _typelib_TypeDescriptionReference*, int, _typelib_MethodParameter*, void*, void**, _uno_Any**) at bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx:233:13
> #9 in unoInterfaceProxyDispatch at bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx:413:13
> #10 in binaryurp::IncomingRequest::execute_throw(binaryurp::BinaryAny*, std::__debug::vector<binaryurp::BinaryAny, std::allocator<binaryurp::BinaryAny>>*) const at binaryurp/source/incomingrequest.cxx:236:13
> #11 in binaryurp::IncomingRequest::execute() const at binaryurp/source/incomingrequest.cxx:79:26
> #12 in request at binaryurp/source/reader.cxx:86:9
> #13 in cppu_threadpool::JobQueue::enter(void const*, bool) at cppu/source/threadpool/jobqueue.cxx:100:17
> #14 in cppu_threadpool::ORequestThread::run() at cppu/source/threadpool/thread.cxx:165:31
>
> 0x60f00014d718 is located 120 bytes inside of 168-byte region [0x60f00014d6a0,0x60f00014d748)
> freed by thread T0 here:
> #0 in operator delete(void*, unsigned long) at ~/github.com/llvm/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:164:3
> #1 in SvTreeListEntry::~SvTreeListEntry() at vcl/source/treelist/treelistentry.cxx:62:1
> #2 in std::default_delete<SvTreeListEntry>::operator()(SvTreeListEntry*) const at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/unique_ptr.h:102:2
> #3 in std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>::~unique_ptr() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/unique_ptr.h:407:4
> #4 in void std::destroy_at<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>(std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_construct.h:88:15
> #5 in void std::_Destroy<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>(std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_construct.h:149:7
> #6 in void std::_Destroy_aux<false>::__destroy<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*>(std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*, std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_construct.h:163:6
> #7 in void std::_Destroy<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*>(std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*, std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_construct.h:195:7
> #8 in void std::_Destroy<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*, std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>(std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*, std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*, std::allocator<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>&) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/alloc_traits.h:947:7
> #9 in std::__cxx1998::vector<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>, std::allocator<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>>::_M_erase_at_end(std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>*) at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_vector.h:1932:6
> #10 in std::__cxx1998::vector<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>, std::allocator<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>>::clear() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_vector.h:1601:9
> #11 in std::__debug::vector<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>, std::allocator<std::unique_ptr<SvTreeListEntry, std::default_delete<SvTreeListEntry>>>>::clear() at ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/debug/vector:729:9
> #12 in SvTreeListEntry::ClearChildren() at vcl/source/treelist/treelistentry.cxx:28:16
> #13 in SvTreeList::Clear() at vcl/source/treelist/treelist.cxx:123:16
> #14 in SvTreeListBox::Clear() at vcl/source/treelist/treelistbox.cxx:422:17
> #15 in SalInstanceTreeView::clear() at vcl/source/app/salvtables.cxx:4240:18
> #16 in SwFieldRefPage::Reset(SfxItemSet const*) at sw/source/ui/fldui/fldref.cxx:175:16
> #17 in SwFieldPage::EditNewField(bool) at sw/source/ui/fldui/fldpage.cxx:111:5
> #18 in SwFieldDlg::ReInitTabPage(std::basic_string_view<char, std::char_traits<char>>, bool) at sw/source/ui/fldui/fldtdlg.cxx:218:16
> #19 in SwFieldDlg::Activate() at sw/source/ui/fldui/fldtdlg.cxx:239:9
> #20 in SwChildWinWrapper::UpdateHdl(Timer*) at sw/source/uibase/fldui/fldwrap.cxx:42:26
> #21 in SwChildWinWrapper::LinkStubUpdateHdl(void*, Timer*) at sw/source/uibase/fldui/fldwrap.cxx:39:1
> #22 in Link<Timer*, void>::Call(Timer*) const at include/tools/link.hxx:111:45
> #23 in Timer::Invoke() at vcl/source/app/timer.cxx:75:21
> #24 in Scheduler::CallbackTaskScheduling() at vcl/source/app/scheduler.cxx:481:20
> #25 in SalTimer::CallCallback() at vcl/inc/saltimer.hxx:54:13
> #26 in SvpSalInstance::CheckTimeout(bool) at vcl/headless/svpinst.cxx:161:53
> #27 in SvpSalInstance::ImplYield(bool, bool) at vcl/headless/svpinst.cxx:399:17
> #28 in SvpSalInstance::DoYield(bool, bool) at vcl/headless/svpinst.cxx:471:21
> #29 in ImplYield(bool, bool) at vcl/source/app/svapp.cxx:475:48
> #30 in Application::Yield() at vcl/source/app/svapp.cxx:559:5
> #31 in Application::Execute() at vcl/source/app/svapp.cxx:453:13
> #32 in desktop::Desktop::Main() at desktop/source/app/app.cxx:1604:13
causing
> ERROR: test_tdf135938_cross_reference_update (tdf135938.tdf135938)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
> File "uitest/uitest/test.py", line 125, in execute_dialog_through_command
> yield xDialog
> File "uitest/uitest/test.py", line 140, in execute_modeless_dialog_through_command
> yield xDialog
> File "sw/qa/uitest/writer_tests7/tdf135938.py", line 40, in test_tdf135938_cross_reference_update
> self.assertEqual("ABC", get_state_as_dict(xSelect.getChild(0))["Text"])
> File "uitest/uitest/uihelper/common.py", line 13, in get_state_as_dict
> return convert_property_values_to_dict(ui_object.getState())
> uitest.uihelper.common.com.sun.star.lang.DisposedException: Binary URP bridge disposed during call at binaryurp/source/bridge.cxx:613
The issue apparently is that TreeListEntryUIObject UNO objects, introduced in
71f562f8f77f14b76fde4329f7238fe2e7d6a054 "uitest: support tree lists", reference
SvTreeListEntry instances by pointers that can apparently go stale while those
UNO objects are still alive. I'm not sure there would be an easy fix for this,
short of making those SvTreeListEntry instances ref-counted, or ripping out
UITest support for those TreeListEntryUIObjects again.
However, that underlying issue would presumably not be of practical concern if
the test_tdf135938_cross_reference_update Python code would have waited for
processEventsToIdle between its
> xInsert.executeAction("CLICK", tuple())
and the following block
> self.assertEqual("2", get_state_as_dict(xSelect)["Children"])
> self.assertEqual("ABC", get_state_as_dict(xSelect.getChild(0))["Text"])
> self.assertEqual("DEF", get_state_as_dict(xSelect.getChild(1))["Text"])
That way, there should be no more opportunity for the pointers in the passed-out
TreeListEntryUIObjects to become stale while the Python code accesses them.
And in Python UITest code, having to follow a call to executeAction by a call to
processEventsToIdle appears to be a common and recurring requirement, just look
at the most recent af1ca684bb12ff62e3df995ad44aefdb57a51af7 "another stab at
making this test reliable", d183daea1abbd7b564d083298874dd7c40d5a5b3
"tdf#153161: (Ab)use a call to XTextRange::getString to flush edits",
3cc6b870c48b23418f65d2c3cd6eab72ef0680de "make an effort to fix the
UITest_inputLine intermittent failure", f4668540ff7256bb0ddd382dfaf9f3499e99128a
"tdf#150443 sw: fix crash of rejecting table row deletion".
So make executeAction always call ProcessEventsToIdle, to simplify this and
hopefully make UITests more robust. (Removing any now-redundant calls to
processEventsToIdle, following calls to executeAction, from Python test code is
left as follow-up clean up for now.)
(I /think/ that the implementation of UIObjectUnoObj::executeAction could be
simplified now, as waiting for Scheduler::ProcessEventsToIdle() should already
make sure that aIdle has been processed, removing the need for the Notifier.
But lets leave that as a follow-up TODO for now.)
Change-Id: I41a5d51515dedaae44fb810b0ad3b0264c90abf3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146434
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/uitest/uno/uiobject_uno.cxx | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/vcl/source/uitest/uno/uiobject_uno.cxx b/vcl/source/uitest/uno/uiobject_uno.cxx index 042b2fcf5cbb..06ec96a45ab6 100644 --- a/vcl/source/uitest/uno/uiobject_uno.cxx +++ b/vcl/source/uitest/uno/uiobject_uno.cxx @@ -19,6 +19,7 @@ #include <comphelper/propertyvalue.hxx> #include <cppuhelper/supportsservice.hxx> #include <tools/link.hxx> +#include <vcl/scheduler.hxx> #include <vcl/svapp.hxx> #include <vcl/idle.hxx> #include <vcl/window.hxx> @@ -153,6 +154,7 @@ void SAL_CALL UIObjectUnoObj::executeAction(const OUString& rAction, const css:: SolarMutexGuard aGuard; aIdle.reset(); + Scheduler::ProcessEventsToIdle(); } css::uno::Sequence<css::beans::PropertyValue> UIObjectUnoObj::getState() |