-
Notifications
You must be signed in to change notification settings - Fork 151
Open
Labels
DoneDoneDone
Description
You can reproduce it with following code:
TEST(thread11, test2)
{
struct Foo {
Foo() {
std::cout << this << ":Foo ctor" << std::endl;
}
Foo(const Foo&) {
std::cout << this << ":Foo copy ctor" << std::endl;
}
Foo(Foo&&) = delete;
// Foo(Foo&&) {
// std::cout << this << ":Foo move ctor" << std::endl;
// }
~Foo() {
std::cout << this << ":Foo dtor" << std::endl;
}
int x = 100;
};
{
Foo foo;
std::cout << "thread_create11" << std::endl;
auto th = thread_create11([foo]{
std::cout << &foo << ":thread" << std::endl;
std::cout << foo.x << std::endl;
});
auto jh = thread_enable_join(th);
thread_join(jh);
}
std::cout << "end" << std::endl;
}
There are 4 ctor invoked, but only 3 dtor invoked.
output:
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from thread11
[ RUN ] thread11.test2
0x7fff42cd2460:Foo ctor
thread_create11
0x7fff42cd2470:Foo copy ctor
0x7fff42cd2390:Foo copy ctor
0x7f5573cfbbb8:Foo copy ctor
0x7fff42cd2390:Foo dtor
0x7fff42cd2470:Foo dtor
0x7f5573cfbbb8:thread
100
0x7fff42cd2460:Foo dtor
end
[ OK ] thread11.test2 (1 ms)
[----------] 1 test from thread11 (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (1 ms total)
[ PASSED ] 1 test.
Tracer caught signal 11: addr=0x7f5573cff000 pc=0x516cf0 sp=0x7f55734f9c90
==3367528==LeakSanitizer has encountered a fatal error.
==3367528==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==3367528==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
There is a bug in the implementation of __thread_create11:
template<typename F, typename SavedArgs, typename...ARGUMENTS> inline
thread* __thread_create11(uint64_t stack_size, F&& f, ARGUMENTS&&...args) {
using Pair = std::pair<F, SavedArgs>;
static_assert(sizeof(Pair) < UINT16_MAX, "...");
auto th = thread_create(&__stub11<Pair>, nullptr, stack_size, sizeof(Pair));
auto p = thread_reserved_space<Pair>(th);
// Here, placement new is called only on the address of p, but no destructor is called anywhere.
// A memory leak occurred if F or ARGUMENTS need to destruct some resource in its destructor method
new (p) Pair{std::forward<F>(f), SavedArgs{std::forward<ARGUMENTS>(args)...}};
return th;
}