ros / class_loader

ROS-independent library for dynamic class (i.e. plugin) introspection and loading from runtime libraries
http://www.ros.org/wiki/class_loader
34 stars 95 forks source link

make sanitizer happy #205

Closed iuhilnehc-ynos closed 1 year ago

iuhilnehc-ynos commented 1 year ago

related to https://github.com/ros/class_loader/pull/201#issuecomment-1287109359

The CI logs will be expired in the future and might no longer be available, so I copy the log as follows,

MultiLibraryClassLoader memory leak

```shell ==6769==ERROR: LeakSanitizer: detected memory leaks Direct leak of 144 byte(s) in 1 object(s) allocated from: #0 0x7efc617811c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99 #1 0x7efc616bac16 in class_loader::MultiLibraryClassLoader::loadLibrary(std::__cxx11::basic_string, std::allocator > const&) /root/target_ws/src/class_loader/src/multi_library_class_loader.cpp:96 #2 0x56419df31a12 in MultiClassLoaderTest_noWarningOnLazyLoad_Test::TestBody() /root/target_ws/src/class_loader/test/utest.cpp:380 #3 0x56419df88576 in void testing::internal::HandleSehExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 #4 0x56419df8129e in void testing::internal::HandleExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2469 #5 0x56419df5b755 in testing::Test::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2508 #6 0x56419df5c19a in testing::TestInfo::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2684 #7 0x56419df5c8fb in testing::TestSuite::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2816 #8 0x56419df68f10 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:5338 #9 0x56419df89a68 in bool testing::internal::HandleSehExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 #10 0x56419df824b2 in bool testing::internal::HandleExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2469 #11 0x56419df676f2 in testing::UnitTest::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:4925 #12 0x56419df3871f in RUN_ALL_TESTS() (/root/target_ws/build/class_loader/test/class_loader_utest+0x3271f) #13 0x56419df33fe6 in main /root/target_ws/src/class_loader/test/utest.cpp:448 #14 0x7efc6110fd8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) Direct leak of 144 byte(s) in 1 object(s) allocated from: #0 0x7efc617811c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99 #1 0x7efc616bac16 in class_loader::MultiLibraryClassLoader::loadLibrary(std::__cxx11::basic_string, std::allocator > const&) /root/target_ws/src/class_loader/src/multi_library_class_loader.cpp:96 #2 0x56419df31a2b in MultiClassLoaderTest_noWarningOnLazyLoad_Test::TestBody() /root/target_ws/src/class_loader/test/utest.cpp:381 #3 0x56419df88576 in void testing::internal::HandleSehExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 #4 0x56419df8129e in void testing::internal::HandleExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2469 #5 0x56419df5b755 in testing::Test::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2508 #6 0x56419df5c19a in testing::TestInfo::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2684 #7 0x56419df5c8fb in testing::TestSuite::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2816 #8 0x56419df68f10 in testing::internal::UnitTestImpl::RunAllTests() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:5338 #9 0x56419df89a68 in bool testing::internal::HandleSehExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 #10 0x56419df824b2 in bool testing::internal::HandleExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2469 #11 0x56419df676f2 in testing::UnitTest::Run() /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:4925 #12 0x56419df3871f in RUN_ALL_TESTS() (/root/target_ws/build/class_loader/test/class_loader_utest+0x3271f) #13 0x56419df33fe6 in main /root/target_ws/src/class_loader/test/utest.cpp:448 #14 0x7efc6110fd8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) Indirect leak of 64 byte(s) in 2 object(s) allocated from: #0 0x7efc617811c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99 #1 0x7efc61563ad9 in void std::__cxx11::basic_string, std::allocator >::_M_construct(char*, char*, std::forward_iterator_tag) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x14ead9) SUMMARY: AddressSanitizer: 352 byte(s) leaked in 4 allocation(s). ```

potential dead lock

```shell WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=7271) Cycle in lock order graph: M98 (0x7b24000001e8) => M99 (0x7b2400000218) => M98 Mutex M99 acquired here while holding mutex M98 in main thread: #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908) #1 __gthread_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d1ff) #2 __gthread_recursive_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d283) #3 std::recursive_mutex::lock() (class_loader_unique_ptr_test+0x1d852) #4 class_loader::ClassLoader::unloadLibraryInternal(bool) /root/target_ws/src/class_loader/src/class_loader.cpp:122 (libclass_loader.so+0x37513) #5 void testing::internal::HandleSehExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 (class_loader_unique_ptr_test+0x64238) #6 main /root/target_ws/src/class_loader/test/unique_ptr_test.cpp:295 (class_loader_unique_ptr_test+0x1baf8) Hint: use TSAN_OPTIONS=second_deadlock_stack=1 to get more informative warning message Mutex M98 acquired here while holding mutex M99 in main thread: #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908) #1 __gthread_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d1ff) #2 __gthread_recursive_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d283) #3 std::recursive_mutex::lock() (class_loader_unique_ptr_test+0x1d852) #4 std::lock_guard::lock_guard(std::recursive_mutex&) (class_loader_unique_ptr_test+0x22be4) #5 class_loader::ClassLoader::unloadLibraryInternal(bool) /root/target_ws/src/class_loader/src/class_loader.cpp:120 (libclass_loader.so+0x374fd) #6 void std::__invoke_impl(std::__invoke_memfun_deref, void (class_loader::ClassLoader::*&)(Base*), class_loader::ClassLoader*&, Base*&&) (class_loader_unique_ptr_test+0x2b939) #7 std::__invoke_result::type std::__invoke(void (class_loader::ClassLoader::*&)(Base*), class_loader::ClassLoader*&, Base*&&) (class_loader_unique_ptr_test+0x2ad29) #8 void std::_Bind))(Base*)>::__call(std::tuple&&, std::_Index_tuple<0ul, 1ul>) (class_loader_unique_ptr_test+0x29efd) #9 void std::_Bind))(Base*)>::operator()(Base*&&) (class_loader_unique_ptr_test+0x286fe) #10 void std::__invoke_impl))(Base*)>&, Base*>(std::__invoke_other, std::_Bind))(Base*)>&, Base*&&) (class_loader_unique_ptr_test+0x26557) #11 std::enable_if, std::__is_invocable))(Base*)>&, Base*> >::value, void>::type std::__invoke_r))(Base*)>&, Base*>(std::_Bind))(Base*)>&, Base*&&) (class_loader_unique_ptr_test+0x24783) #12 std::_Function_handler))(Base*)> >::_M_invoke(std::_Any_data const&, Base*&&) (class_loader_unique_ptr_test+0x22def) #13 std::function::operator()(Base*) const (class_loader_unique_ptr_test+0x2118c) #14 std::unique_ptr >::~unique_ptr() (class_loader_unique_ptr_test+0x1efe8) #15 MultiClassLoaderUniquePtrTest_noWarningOnLazyLoad_Test::TestBody() /root/target_ws/src/class_loader/test/unique_ptr_test.cpp:284 (class_loader_unique_ptr_test+0x1b76e) #16 void testing::internal::HandleSehExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 (class_loader_unique_ptr_test+0x64238) #17 main /root/target_ws/src/class_loader/test/unique_ptr_test.cpp:295 (class_loader_unique_ptr_test+0x1baf8) SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) (/root/target_ws/build/class_loader/test/class_loader_unique_ptr_test+0x1d1ff) in __gthread_mutex_lock(pthread_mutex_t*) ================== ================== WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=7271) Cycle in lock order graph: M96 (0x7b24000000c8) => M97 (0x7b24000000f8) => M96 Mutex M97 acquired here while holding mutex M96 in main thread: #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908) #1 __gthread_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d1ff) #2 __gthread_recursive_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d283) #3 std::recursive_mutex::lock() (class_loader_unique_ptr_test+0x1d852) #4 class_loader::ClassLoader::unloadLibraryInternal(bool) /root/target_ws/src/class_loader/src/class_loader.cpp:122 (libclass_loader.so+0x37513) #5 void testing::internal::HandleSehExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 (class_loader_unique_ptr_test+0x64238) #6 main /root/target_ws/src/class_loader/test/unique_ptr_test.cpp:295 (class_loader_unique_ptr_test+0x1baf8) Hint: use TSAN_OPTIONS=second_deadlock_stack=1 to get more informative warning message Mutex M96 acquired here while holding mutex M97 in main thread: #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908) #1 __gthread_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d1ff) #2 __gthread_recursive_mutex_lock(pthread_mutex_t*) (class_loader_unique_ptr_test+0x1d283) #3 std::recursive_mutex::lock() (class_loader_unique_ptr_test+0x1d852) #4 std::lock_guard::lock_guard(std::recursive_mutex&) (class_loader_unique_ptr_test+0x22be4) #5 class_loader::ClassLoader::unloadLibraryInternal(bool) /root/target_ws/src/class_loader/src/class_loader.cpp:120 (libclass_loader.so+0x374fd) #6 void std::__invoke_impl(std::__invoke_memfun_deref, void (class_loader::ClassLoader::*&)(Base*), class_loader::ClassLoader*&, Base*&&) (class_loader_unique_ptr_test+0x2b939) #7 std::__invoke_result::type std::__invoke(void (class_loader::ClassLoader::*&)(Base*), class_loader::ClassLoader*&, Base*&&) (class_loader_unique_ptr_test+0x2ad29) #8 void std::_Bind))(Base*)>::__call(std::tuple&&, std::_Index_tuple<0ul, 1ul>) (class_loader_unique_ptr_test+0x29efd) #9 void std::_Bind))(Base*)>::operator()(Base*&&) (class_loader_unique_ptr_test+0x286fe) #10 void std::__invoke_impl))(Base*)>&, Base*>(std::__invoke_other, std::_Bind))(Base*)>&, Base*&&) (class_loader_unique_ptr_test+0x26557) #11 std::enable_if, std::__is_invocable))(Base*)>&, Base*> >::value, void>::type std::__invoke_r))(Base*)>&, Base*>(std::_Bind))(Base*)>&, Base*&&) (class_loader_unique_ptr_test+0x24783) #12 std::_Function_handler))(Base*)> >::_M_invoke(std::_Any_data const&, Base*&&) (class_loader_unique_ptr_test+0x22def) #13 std::function::operator()(Base*) const (class_loader_unique_ptr_test+0x2118c) #14 std::unique_ptr >::~unique_ptr() (class_loader_unique_ptr_test+0x1efe8) #15 MultiClassLoaderUniquePtrTest_noWarningOnLazyLoad_Test::TestBody() /root/target_ws/src/class_loader/test/unique_ptr_test.cpp:284 (class_loader_unique_ptr_test+0x1b78c) #16 void testing::internal::HandleSehExceptionsInMethodIfSupported(testing::Test*, void (testing::Test::*)(), char const*) /opt/ros/rolling/src/gtest_vendor/./src/gtest.cc:2433 (class_loader_unique_ptr_test+0x64238) #17 main /root/target_ws/src/class_loader/test/unique_ptr_test.cpp:295 (class_loader_unique_ptr_test+0x1baf8) SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) ```

Signed-off-by: Chen Lihui lihui.chen@sony.com

iuhilnehc-ynos commented 1 year ago

sanitizer seems happy, https://github.com/iuhilnehc-ynos/class_loader/actions/runs/3311503280/jobs/5467034199

iuhilnehc-ynos commented 1 year ago

CI:

iuhilnehc-ynos commented 1 year ago

retry CI:

iuhilnehc-ynos commented 1 year ago

CI:

retry CI:

fujitatomoya commented 1 year ago

@iuhilnehc-ynos is this ready to review?

gbiggs commented 1 year ago
fujitatomoya commented 1 year ago

@gbiggs can you merge this, we do not have permission on this repo.

gbiggs commented 1 year ago

Sure! Thanks for checking.