https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60966
--- Comment #14 from Hideaki Kimura <hideaki.kimura at gmail dot com> ---
(In reply to Jonathan Wakely from comment #13)
> This means you are waiting on an object that has gone out of scope. WIthout
> more information it's not possible to tell if this is a bug in your program
> or the standard libary.
>
> I'll try to reproduce it with Thomas's code...
Hey Jonathan,
I'm not sure if this helps, but could you try the following code snippet?
#include <future>
#include <iostream>
#include <thread>
#include <vector>
struct DummyTask {
DummyTask(int id) : id_(id) {}
int id_;
std::promise<void> pr;
};
const int THREADS = 100;
void run_task(DummyTask* task) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
task->pr.set_value();
}
void wait_for_task(DummyTask* task) {
task->pr.get_future().wait();
}
int main() {
std::vector<DummyTask*> tasks;
std::vector<std::thread*> threads;
for (int i = 0; i < THREADS; ++i) {
DummyTask* task = new DummyTask(i);
tasks.push_back(task);
threads.push_back(new std::thread(run_task, task));
}
for (int i = 0; i < THREADS; ++i) {
wait_for_task(tasks[i]);
// Because we returned from wait_for_task for this task, run_task is
surely done.
// No one else is referring to the task. So, even before
threads[i]->join(),
// it should be safe to delete it now.
delete tasks[i]; // but here you get an invalid read!
}
for (int i = 0; i < THREADS; ++i) {
threads[i]->join();
delete threads[i];
}
return 0;
}
Run it a few times on valgrind. You will see what I got.
If you move threads[i]->join() to the line before delete tasks[i], you don't
get the issue.
[Assuming that I'm not terribly missing something..]
My bet is that std::promise puts something on thread-local, which causes some
issue when std::promise's destructor is called before the corresponding
thread's join() is called.