[Bug libstdc++/60966] std::call_once sometime hangs

2014-05-13 Thread hideaki.kimura at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60966

Hideaki Kimura  changed:

   What|Removed |Added

 CC||hideaki.kimura at gmail dot com

--- Comment #11 from Hideaki Kimura  ---
Hi, I'm also (seemingly) hitting this issue.
When I run my program with valgrind, I get what Thomas reported.

==22319== Invalid read of size 4
==22319==at 0x370940D201: pthread_once (pthread_once.S:111)
==22319==by 0x4C80524:  (gthr-default.h:699)
...
==22319==  Address 0x52c52a4 is 132 bytes inside a block of size 136 free'd
==22319==at 0x4A07991: operator delete(void*) (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==22319==by 0x4C82456: ... (shared_ptr_base.h:161)
==22319==by 0x370C4B52AF: execute_native_thread_routine (thread.cc:84)
==22319==by 0x3709407F32: start_thread (pthread_create.c:309)
==22319==by 0x37090F4DEC: clone (clone.S:111)
==22319== 

My environment is Fedora 20, x86_64, g++ (GCC) 4.8.2 20131212 (Red Hat
4.8.2-7).
Any workaround?


[Bug libstdc++/60966] std::call_once sometime hangs

2014-05-14 Thread hideaki.kimura at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60966

--- Comment #14 from Hideaki Kimura  ---
(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 
#include 
#include 
#include 

struct DummyTask {
DummyTask(int id) : id_(id) {}
int id_;
std::promise 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 tasks;
std::vector 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.


[Bug libstdc++/60966] std::call_once sometime hangs

2014-05-15 Thread hideaki.kimura at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60966

--- Comment #17 from Hideaki Kimura  ---
(In reply to Jonathan Wakely from comment #16)
> promise::get_future() is a non-const function that modifies the promise
> object, therefore it must not be called while any other object is accessing
> the promise.
Oh, is it the design of promise::get_future/set_value?
I so far don't see any reference that clarifies either way (most document just
mentions about difference between future/shared_future)

Taking a glance at boost::promise code, I got an impression that their code is
safe against concurrent get_future() and set_value() because get_future()
either does atomic swap in lazy_init() or does nothing (allocated in
constructor).
I guess that's why Thomas observed that the issue doesn't happen in
boost::promise.

I'm not sure what the C++ standard says. I haven't seen a single human being
who has read it through.


[Bug libstdc++/60966] std::call_once sometime hangs

2014-05-15 Thread hideaki.kimura at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60966

--- Comment #22 from Hideaki Kimura  ---
Ah, you are right, set_value() might have context switch after signaling before
exitting.

... ah, and that's why what Thomas initially posted could also see a hang.
{ // copy-paste again to refresh memory, with some simplification
std::promise promise;
auto future = promise.get_future();
std::async or thread ( {promise.set_value();});
future.get();
}

The user of std::promise must make sure the asynchronous thread has surely
exitted at least from promise.set_value() before std::promise gets out of
scope.
promise/future is a handy way to synchronize between threads, but to use it one
must protect it with thread synchronization..? That's quite tedious.


I've just seen the patch as of writing this comment. I guess it solves the
issue?

(In reply to Jonathan Wakely from comment #19)
> (In reply to Jonathan Wakely from comment #16)
> > The easiest fix is to call get_future() before passing the task into a new
> > thread, and store it in a std::vector>
> 
> Actually this only hides the error (by ensuring the shared state is not
> deleted
> because there is a future object still referring to it) but the fundamental
> problem with that code remains:
> 
> You are calling the promise destructor before the call to set_value()
> completes.
> 
> You are assuming that as soon as the shared state becomes ready the promise
> is no longer in use, but that's not true. After the shared state is made
> ready the rest of the set_value() function runs, which accesses members of
> the shared state. If you destroy the promise (and it has the only reference
> to the shared state) then it will destroy its members while they are still
> being used.
> 
> This is a bug in your code, std::promise is like any other type: you must
> not delete it while another thread is still using it.