[thread] race condition detected with valgrind drd

Dear all, I must be doing something wrong, but I can't figure out what. I would appreciate some help. Thank you in advance. The following program: #include <boost/thread.hpp> void threadEntry() { } int main (int argc, char *argv[]) { for(size_t t=0; t<10; t++) { boost::thread(threadEntry); } } runs cleanly with valgrind drd, but this other program produces race conditions when run with valgrind drd (see below). The only difference is "new". #include <boost/thread.hpp> void threadEntry() { } int main (int argc, char *argv[]) { for(size_t t=0; t<10; t++) { new boost::thread(threadEntry); } } This problem is not due to the leak, because this other program: #include <boost/thread.hpp> #include <boost/shared_ptr.hpp> void threadEntry() { } int main (int argc, char *argv[]) { std::vector<boost::shared_ptr<boost::thread> > threads; for(size_t t=0; t<10; t++) { boost::shared_ptr<boost::thread> thread(new boost::thread( threadEntry )); threads.push_back(thread); } for (size_t i = 0; i < threads.size(); ++i) { threads[i]->join(); } } which properly manages the heap also produces the same race conditions. I compile using: g++ -g -L /opt/boost/boost/stage/lib -lboost_thread threads.cpp and I test the program using valgrind using: valgrind --tool=drd ./a.out The output of valgrind is: ==3822== drd, a thread error detector ==3822== Copyright (C) 2006-2009, and GNU GPL'd, by Bart Van Assche. ==3822== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info ==3822== Command: ./a.out ==3822== ==3822== Thread 3: ==3822== Conflicting store by thread 3 at 0x0504b350 size 8 ==3822== at 0x4E417B3: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== Allocation context: BSS section of /usr/local/lib/libboost_thread.so.1.42.0 ==3822== Other segment start (thread 2) ==3822== at 0x58D67D1: clone (clone.S:84) ==3822== by 0x5D7493F: ??? (allocatestack.c:743) ==3822== by 0x6B8A90F: ??? ==3822== Other segment end (thread 2) ==3822== at 0x5D7A7C4: pthread_once (pthread_once.S:119) ==3822== by 0x4C28ADD: pthread_once (drd_pthread_intercepts.c:518) ==3822== by 0x4E473B3: boost::detail::get_once_per_thread_epoch() (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E4172F: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== ==3822== Conflicting store by thread 3 at 0x0504b350 size 8 ==3822== at 0x4E417F9: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== Allocation context: BSS section of /usr/local/lib/libboost_thread.so.1.42.0 ==3822== Other segment start (thread 2) ==3822== at 0x58D67D1: clone (clone.S:84) ==3822== by 0x5D7493F: ??? (allocatestack.c:743) ==3822== by 0x6B8A90F: ??? ==3822== Other segment end (thread 2) ==3822== at 0x5D7A7C4: pthread_once (pthread_once.S:119) ==3822== by 0x4C28ADD: pthread_once (drd_pthread_intercepts.c:518) ==3822== by 0x4E473B3: boost::detail::get_once_per_thread_epoch() (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E4172F: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== Other segment start (thread 2) ==3822== at 0x58D67D1: clone (clone.S:84) ==3822== by 0x5D7493F: ??? (allocatestack.c:743) ==3822== by 0x6B8A90F: ??? ==3822== Other segment end (thread 2) ==3822== at 0x5D7A7C4: pthread_once (pthread_once.S:119) ==3822== by 0x4C28ADD: pthread_once (drd_pthread_intercepts.c:518) ==3822== by 0x4E473B3: boost::detail::get_once_per_thread_epoch() (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E4172F: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== ==3822== Conflicting load by thread 3 at 0x05f85288 size 8 ==3822== at 0x5D73AEE: __nptl_deallocate_tsd (pthread_create.c:153) ==3822== by 0x5D74A11: start_thread (pthread_create.c:307) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== Allocation context: BSS section of /lib/libpthread-2.10.1.so ==3822== Other segment start (thread 2) ==3822== at 0x58D67D1: clone (clone.S:84) ==3822== by 0x5D7493F: ??? (allocatestack.c:743) ==3822== by 0x6B8A90F: ??? ==3822== Other segment end (thread 2) ==3822== at 0x5D7A7C4: pthread_once (pthread_once.S:119) ==3822== by 0x4C28ADD: pthread_once (drd_pthread_intercepts.c:518) ==3822== by 0x4E473B3: boost::detail::get_once_per_thread_epoch() (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E4172F: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== ==3822== Thread 4: ==3822== Conflicting load by thread 4 at 0x0504b350 size 8 ==3822== at 0x4E41724: ??? (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E41B28: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4E42124: thread_proxy (in /usr/local/lib/libboost_thread.so.1.42.0) ==3822== by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272) ==3822== by 0x5D74A03: start_thread (pthread_create.c:300) ==3822== by 0x58D680C: clone (clone.S:112) ==3822== Allocation context: BSS section of /usr/local/lib/libboost_thread.so.1.42.0 ==3822== Other segment start (thread 3) ==3822== (thread finished, call stack no longer available) ==3822== Other segment end (thread 3) ==3822== (thread finished, call stack no longer available) ==3822== Other segment start (thread 3) ==3822== (thread finished, call stack no longer available) ==3822== Other segment end (thread 3) ==3822== (thread finished, call stack no longer available) ==3822== ==3822== ==3822== For counts of detected and suppressed errors, rerun with: -v ==3822== ERROR SUMMARY: 11 errors from 4 contexts (suppressed: 126 from 76)

Jorge Moraleda <moraleda@rii.ricoh.com> writes:
I must be doing something wrong, but I can't figure out what. I would appreciate some help. Thank you in advance.
The following program:
#include <boost/thread.hpp>
void threadEntry() { }
int main (int argc, char *argv[]) { for(size_t t=0; t<10; t++) { boost::thread(threadEntry); } }
runs cleanly with valgrind drd, but this other program produces race conditions when run with valgrind drd (see below). The only difference is "new".
#include <boost/thread.hpp>
void threadEntry() { }
int main (int argc, char *argv[]) { for(size_t t=0; t<10; t++) { new boost::thread(threadEntry); } }
I don't know why the result is different. Maybe the result is different because the compiler optimizes the code differently. Anyway, it looks like the detected race is in call_once. The code there relies on the fact that reading and writing integers is atomic, so you'll never get a part-updated value, even if the value read is stale. This is technically a race, but works on common platforms. Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
participants (2)
-
Anthony Williams
-
Jorge Moraleda