Rob*_*ser 10 c++ boost pthreads boost-thread thread-local
When the application is shutting down Valgrind reports these 3 issues:
==70== Mismatched free() / delete / delete []
==70== at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==70== by 0x4870C89: check_free (dlerror.c:202)
==70== by 0x4870C89: check_free (dlerror.c:186)
==70== by 0x4870C89: free_key_mem (dlerror.c:221)
==70== by 0x4870C89: __dlerror_main_freeres (dlerror.c:239)
==70== by 0x4B59711: __libc_freeres (in /usr/lib/x86_64-linux-gnu/libc-2.29.so)
==70== by 0x482E19E: _vgnU_freeres (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_core-amd64-linux.so)
==70== by 0x4A0A3A9: __run_exit_handlers (exit.c:132)
==70== by 0x4A0A3D9: exit (exit.c:139)
==70== by 0x49E9B71: (below main) (libc-start.c:342)
==70== Address 0x4f6a570 is 0 bytes inside a block of size 312 alloc'd
==70== at 0x4838DBF: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==70== by 0x303D6D: boost::detail::make_external_thread_data() (in /build-context/bin/debug/setmatch-tests)
==70== by 0x305424: boost::detail::add_new_tss_node(void const*, boost::shared_ptr<boost::detail::tss_cleanup_function>, void*) (in /build-context/bin/debug/setmatch-tests)
==70== by 0x3054ED: boost::detail::set_tss_data(void const*,
[...]
==70== Invalid free() / delete / delete[] / realloc()
==70== at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==70== by 0x4870BB4: free_key_mem (dlerror.c:223)
==70== by 0x4870BB4: __dlerror_main_freeres (dlerror.c:239)
==70== by 0x4B59711: __libc_freeres (in /usr/lib/x86_64-linux-gnu/libc-2.29.so)
==70== by 0x482E19E: _vgnU_freeres (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_core-amd64-linux.so)
==70== by 0x4A0A3A9: __run_exit_handlers (exit.c:132)
==70== by 0x4A0A3D9: exit (exit.c:139)
==70== by 0x49E9B71: (below main) (libc-start.c:342)
==70== Address 0x4f6a570 is 0 bytes inside a block of size 312 free'd
==70== at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==70== by 0x4870C89: check_free (dlerror.c:202)
==70== by 0x4870C89: check_free (dlerror.c:186)
==70== by 0x4870C89: free_key_mem (dlerror.c:221)
==70== by 0x4870C89: __dlerror_main_freeres (dlerror.c:239)
==70== by 0x4B59711: __libc_freeres (in /usr/lib/x86_64-linux-gnu/libc-2.29.so)
==70== by 0x482E19E: _vgnU_freeres (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_core-amd64-linux.so)
==70== by 0x4A0A3A9: __run_exit_handlers (exit.c:132)
==70== by 0x4A0A3D9: exit (exit.c:139)
==70== by 0x49E9B71: (below main) (libc-start.c:342)
==70== Block was alloc'd at
==70== at 0x4838DBF: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==70== by 0x303D6D: boost::detail::make_external_thread_data() (in /build-context/bin/debug/setmatch-tests)
==70== by 0x305424: boost::detail::add_new_tss_node(void const*, boost::shared_ptr<boost::detail::tss_cleanup_function>, void*) (in /build-context/bin/debug/setmatch-tests)
==70== by 0x3054ED: boost::detail::set_tss_data(void const*, boost::shared_ptr<boost::detail::tss_cleanup_function>, void*, bool) (in /build-context/bin/debug/setmatch-tests)
==70== by 0x188841: boost::thread_specific_ptr<burningmime::setmatch::MatchState>::reset(burningmime::setmatch::MatchState*) (tss.hpp:105)
[...]
==70== 24 bytes in 1 blocks are definitely lost in loss record 1 of 2
==70== at 0x4838DBF: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==70== by 0x303F50: boost::detail::make_external_thread_data() (in /build-context/bin/debug/setmatch-tests)
==70== by 0x305424: boost::detail::add_new_tss_node(void const*, boost::shared_ptr<boost::detail::tss_cleanup_function>, void*) (in /build-context/bin/debug/setmatch-tests)
==70== by 0x3054ED: boost::detail::set_tss_data(void const*, boost::shared_ptr<boost::detail::tss_cleanup_function>, void*, bool) (in /build-context/bin/debug/setmatch-tests)
[...]
Run Code Online (Sandbox Code Playgroud)
It looks like boost is allocating its thread data in the same place that dlerror has allocated its own thread data. A quick search points to a (slightly different?) version of dlerror here
A quick glance over at bosot's code looks to me like it's just allocating the TSS block on the heap.
This was not a problem with GCC 7.3.0 + Ubuntu 18 (same Boost version)
Anyone have some insight here?
如果我像这样修改调用周围的glibc 上游测试用例pthread_setspecific(并使用 编译它g++):
void *ptr = new char;
printf("Setting thread local to ptr.\n");
if (pthread_setspecific(key, ptr) != 0) {
perror("pthread_setspecific");
exit(1);
}
delete ptr;
Run Code Online (Sandbox Code Playgroud)
在修复之前(在提交 5b06f538c5aee0389ed034f60d90a8884d6d54de 处,使用./testrun.sh --tool=valgrind /path/to/testglibc 构建树)运行 glibc 时,我收到此错误:
void *ptr = new char;
printf("Setting thread local to ptr.\n");
if (pthread_setspecific(key, ptr) != 0) {
perror("pthread_setspecific");
exit(1);
}
delete ptr;
Run Code Online (Sandbox Code Playgroud)
这与您遇到的错误几乎相同,减去operator newBoost 中分配的嵌套。所以看起来这两个错误确实是相同的。
这是有道理的:由于bug 24476,libdl使用未初始化的pthread_key_t值(之前没有调用pthread_key_create它)。对于数据段(其中内部密钥libdl存储为0,当然,未初始化意味着零,并且正如您从测试中的诊断输出中看到的那样,测试分配的密钥(在您的情况下是Boost)实际上是密钥0 :
key = 0
Run Code Online (Sandbox Code Playgroud)
这段libdl代码相当复杂,我发布了一个补丁,该补丁dlerror移至 libc(来自 libdl),并且还完全避免使用 POSIX 线程线程本地存储。
总结一下:无论谁维护您使用的 glibc 版本,都需要将上游修复程序向后移植到其源代码树中并发布更新。 我们也必须这样做。从好的方面来说,这个错误仅当您在 valgrind 和类似工具下运行应用程序时才会发生,因为在常规进程关闭期间,__libc_freeres不会调用该错误:进程无论如何都会很快退出,并且内核会为我们清理所有资源。除非您在生产中使用 valgrind,否则这意味着您永远不会遇到此错误。当然,当你使用 valgrind 进行调试时,这仍然是一个恼人的问题。对于那个很抱歉。