don't return impl by shared_ptr

Thread 1 exits, and TimerManagerImpl dtor reduces its m_pImpl shared_ptr of
TimerManager to use_count 0 triggering dtor of its contents. That dtor
waits for Thread 2 to join.

Thread 2 calls checkForTimeout which calls TimerManagerImpl::unregisterTimer.
whose m_pImpl is still set, but with a use_count is 0. Return by value
results in a temp std::shared_ptr of use_count 0 which on going out of scope
triggers a second dtor of m_pImpl.

Work around this by not returning a shared_ptr.

Thread 1 (Thread 0x7ffff7ab5100 (LWP 3274153) "cppunittester"):
 #0  0x00007ffff71509a4 in salhelper::TimerManager::~TimerManager (this=0x508000000da0) at salhelper/source/timer.cxx:269
 #1  0x00007ffff71548c0 in std::_Sp_counted_ptr<salhelper::TimerManager*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (this=0x503000001060) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:428
 #2  0x00007ffff7153d11 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x503000001060) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:346
 #3  0x00007ffff7153b56 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x7ffff715edd8 <(anonymous namespace)::getTimerManager()::aManager+56>) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:1069
 #4  0x00007ffff7154559 in std::__shared_ptr<salhelper::TimerManager, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x7ffff715edd0 <(anonymous namespace)::getTimerManager()::aManager+48>) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:1525
 #5  0x00007ffff7153ae5 in std::shared_ptr<salhelper::TimerManager>::~shared_ptr (this=0x7ffff715edd0 <(anonymous namespace)::getTimerManager()::aManager+48>) at /usr/bin/../lib/gcc/x--Type <RET> for more, q to quit, c to continue without paging--
 86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr.h:175
 #6  0x00007ffff7152759 in (anonymous namespace)::TimerManagerImpl::~TimerManagerImpl (this=0x7ffff715eda0 <(anonymous namespace)::getTimerManager()::aManager>) at salhelper/source/timer.cxx:62
 #7  0x00007ffff7651641 in __run_exit_handlers () from /lib64/libc.so.6
 #8  0x00007ffff765170e in exit () from /lib64/libc.so.6
 #9  0x00007ffff763808f in __libc_start_call_main () from /lib64/libc.so.6
 #10 0x00007ffff763814b in __libc_start_main_impl () from /lib64/libc.so.6
 #11 0x00000000004314e5 in _start ()

Thread 2 (Thread 0x7fffe6fff6c0 (LWP 3274156) "salhelper::Time"):
 #0  salhelper::TimerManager::~TimerManager (this=0x508000000da0) at salhelper/source/timer.cxx:269
 #1  0x00007ffff71548c0 in std::_Sp_counted_ptr<salhelper::TimerManager*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (this=0x503000001060) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:428
 #2  0x00007ffff7154024 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use (this=0x503000001060) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:175
 #3  0x00007ffff7153fb5 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use_cold (this=0x503000001060) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:199
 #4  0x00007ffff7153f6b in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x503000001060) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:353
 #5  0x00007ffff7153b56 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x7fffe58ff268) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:1069
 #6  0x00007ffff7154559 in std::__shared_ptr<salhelper::TimerManager, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x7fffe58ff260) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr_base.h:1525
 #7  0x00007ffff7153ae5 in std::shared_ptr<salhelper::TimerManager>::~shared_ptr (this=0x7fffe58ff260) at /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/shared_ptr.h:175
 #8  0x00007ffff714fa2c in (anonymous namespace)::TimerManagerImpl::unregisterTimer (this=0x7ffff715eda0 <(anonymous namespace)::getTimerManager()::aManager>, pTimer=0x50d0000001e0) at salhelper/source/timer.cxx:100
 #9  0x00007ffff714f4b5 in salhelper::Timer::stop (this=0x50d0000001e0) at salhelper/source/timer.cxx:159
 #10 0x00007ffff714f465 in salhelper::Timer::~Timer (this=0x50d0000001e0) at salhelper/source/timer.cxx:143
 #11 0x00007ffff7172912 in (anonymous namespace)::TestTimer::~TestTimer() () from workdir/LinkTarget/CppunitTest/libtest_salhelper_testapi.so
 #12 0x00007ffff7172939 in (anonymous namespace)::TestTimer::~TestTimer() () from workdir/LinkTarget/CppunitTest/libtest_salhelper_testapi.so
 #13 0x00007ffff714ea88 in salhelper::SimpleReferenceObject::release() () from instdir/program/libuno_salhelpergcc3.so.3
 #14 0x00007ffff7151be0 in salhelper::TimerManager::checkForTimeout (this=0x508000000da0) at salhelper/source/timer.cxx:410
 #15 0x00007ffff7152189 in salhelper::TimerManager::run (this=0x508000000da0) at salhelper/source/timer.cxx:444
 #16 0x00007ffff714f109 in threadFunc () from instdir/program/libuno_salhelpergcc3.so.3
 #17 0x00007ffff7dbbc31 in osl_thread_start_Impl(void*) () from instdir/program/libuno_sal.so.3
 #18 0x00000000004c84ed in asan_thread_start(void*) ()
 #19 0x00007ffff76a6088 in start_thread () from /lib64/libc.so.6
 #20 0x00007ffff7729f8c in clone3 () from /lib64/libc.so.6

Change-Id: I761ca9db12738415aa0eca386956c762b42b28d3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185868
Tested-by: Jenkins
Tested-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
This commit is contained in:
Caolán McNamara
2025-05-27 09:41:19 +02:00
parent e146daf411
commit c6c8e1c325
+5 -5
View File
@@ -80,26 +80,26 @@ public:
ensureThread();
}
std::shared_ptr<TimerManager> ensureThread()
TimerManager& ensureThread()
{
if (!m_pImpl)
m_pImpl.reset(new TimerManager(m_pHead, m_Lock));
return m_pImpl;
return *m_pImpl;
}
void registerTimer(salhelper::Timer* pTimer)
{
ensureThread()->registerTimer(pTimer);
ensureThread().registerTimer(pTimer);
}
void unregisterTimer(salhelper::Timer * pTimer)
{
ensureThread()->unregisterTimer(pTimer);
ensureThread().unregisterTimer(pTimer);
}
bool lookupTimer(const salhelper::Timer* pTimer)
{
return ensureThread()->lookupTimer(pTimer);
return ensureThread().lookupTimer(pTimer);
}
};