[cfe-users] static thread_local destructor not called at program exit

Roger Liao via cfe-users cfe-users at lists.llvm.org
Wed Dec 9 08:02:35 PST 2015


Hi all,

I've been using static thread_locals and I observed confusing behavior for
thread_local destruction at program exit. In my simplified example, an
object owns a thread and joins on it when the object is destroyed. This is
derived from a thread pool construct.

The object, defined as Wrapper, is held in a static global and I expect it
to be destroyed at the end of main. The issue is that the static
thread_local destructor from the spawned thread owned by Wrapper is not
called and is reported as a leak by leak sanitizer. However, if I destroy
the object before the end of main, the static thread_local destructor is
indeed called.

My understanding is that thread_local destructors should be invoked before
join returns. Why is it that the thread_local destructor is not invoked
when the static global object is destroyed and joins on the thread after
main ends?

In the output below, there is a message for the construction of the
thread_local, but no corresponding message for the destruction of the
thread_local.

clang --version

clang version 3.7.0 (tags/RELEASE_370/final)

Target: x86_64-redhat-linux-gnu

Thread model: posix


clang++ -g -o foo foo.cc -fsanitize=leak -std=c++11 -lpthread

./foo

Started 140182605002496 from 140182628901568

Constructed thread_local from 140182605002496

Joining 140182605002496 from 140182628901568


=================================================================

*==18828==ERROR: LeakSanitizer: detected memory leaks

                                       *

*Direct leak of 24 byte(s) in 1 object(s) allocated from:

                                       *

    #0 0x40a565 in operator new(unsigned long, std::nothrow_t const&)
(/home/rliao/tmp/foo+0x40a565)

    #1 0x424d85 in __cxa_thread_atexit (/home/rliao/tmp/foo+0x424d85)


*Direct leak of 8 byte(s) in 1 object(s) allocated from:

                                       *

    #0 0x40a325 in operator new(unsigned long)
(/home/rliao/tmp/foo+0x40a325)

    #1 0x423273 in foo() /home/rliao/tmp/foo.cc:23:41

    #2 0x424698 in Wrapper::WorkerLoop(void*) /home/rliao/tmp/foo.cc:59:5

    #3 0x7f2ddd1baa50 in start_thread (/lib64/libpthread.so.0+0x7a50)


SUMMARY: LeakSanitizer: 32 byte(s) leaked in 2 allocation(s).

--
Roger Liao
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-users/attachments/20151209/2e641409/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: foo.cc
Type: application/octet-stream
Size: 1907 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-users/attachments/20151209/2e641409/attachment.obj>


More information about the cfe-users mailing list