id summary reporter owner description type status milestone component version severity resolution keywords cc 4531 [Thread] ::promise shared between threads race-condition thijsterlouw@… Anthony Williams "I believe I have discovered a problem with boost::promise when it's shared via threads. I described the problem (informally) on the [http://lists.boost.org/boost-users/2010/08/61530.php boost-users-list]. As suggested by Anthony Williams I raise a ticket for this bug here. Another anonymous helper also suggested that I create a standalone test-case for my bug, which I have done as well. You can find it attached. The test case can be made like this: {{{ g++ -O0 -g -static -I /usr/local/boost_1_43_0 boostpromise.cpp -o boostpromise -L/usr/local/boost_1_43_0/stage/lib/ -lboost_thread -lpthread }}} run like this: ./boostpromise it will do an (endless) loop and usually results in an error (but no crash) or a core-dump (about 50-50 it seems). Either happens usually before several hundred iterations. Expected output is: {{{ ... [11805] ok : 11815 [11806] ok : 11816 [11807] ok : 11817 [11808] ok : 11818 [11809] ok : 11819 [11810] ok : 11820 [11811] ok : 11821 ... }}} When I change the boost file /usr/local/boost_1_43_0/boost/thread/future.hpp and add lazy_init(); in the promise constructor (around line 919), the boostpromise program runs for a million iterations without problems. I guess this is not the best solution, because it's not lazy anymore, but solves my problem for now. {{{ promise(): future(),future_obtained(false) { lazy_init(); } }}} back trace from coredump below: {{{ (gdb) bt #0 0xffffe410 in __kernel_vsyscall () #1 0x08105f78 in raise () #2 0x080d81b2 in abort () #3 0x080d3c3d in __assert_fail () #4 0x08060a4f in ~mutex (this=0x8174330) at /usr/local/boost_1_43_0/boost/thread/pthread/mutex.hpp:46 #5 0x08060ab7 in ~future_object_base (this=0x8174320) at /usr/local/boost_1_43_0/boost/thread/future.hpp:104 #6 0x08060b87 in ~future_object (this=0x8174320) at /usr/local/boost_1_43_0/boost/thread/future.hpp:290 #7 0x0804cc6c in boost::checked_delete > (x=0x8174320) at /usr/local/boost_1_43_0/boost/checked_delete.hpp:34 #8 0x0804dd04 in boost::detail::sp_counted_impl_p >::dispose (this=0x81742d8) at /usr/local/boost_1_43_0/boost/smart_ptr/detail/sp_counted_impl.hpp:78 #9 0x08048894 in boost::detail::sp_counted_base::release (this=0x81742d8) at /usr/local/boost_1_43_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:145 #10 0x080488da in ~shared_count (this=0xbf8d7fc4) at /usr/local/boost_1_43_0/boost/smart_ptr/detail/shared_count.hpp:217 #11 0x080492d2 in ~shared_ptr (this=0xbf8d7fc0) at /usr/local/boost_1_43_0/boost/smart_ptr/shared_ptr.hpp:169 #12 0x08051aa5 in boost::shared_ptr >::reset > (this=0x8171f68, p=0x8174260) at /usr/local/boost_1_43_0/boost/smart_ptr/shared_ptr.hpp:392 #13 0x08061397 in boost::promise::lazy_init (this=0x8171f68) at /usr/local/boost_1_43_0/boost/thread/future.hpp:909 #14 0x080616e8 in boost::promise::get_future (this=0x8171f68) at /usr/local/boost_1_43_0/boost/thread/future.hpp:978 #15 0x08048425 in main () at boostpromise.cpp:70 (gdb) }}} ps, attaching the test file gave a TRAC error ( {{{ OperationalError: database is locked }}} so I just inline it here, boospromise.cpp : {{{ #include class Packet { public: Packet(int i) : in(i) {} int in; }; typedef boost::promise< Packet > packet_promise; typedef boost::shared_ptr< packet_promise > packet_promise_shared_ptr; typedef std::pair< unsigned long, packet_promise_shared_ptr > seq_promise_pair; typedef std::map< unsigned long, packet_promise_shared_ptr > seq_to_promise_map; class Demo { private: boost::thread setvalue_thread_; seq_to_promise_map mymap_; boost::mutex mymap_mutex_; unsigned long counter_; public: Demo() : counter_(10), setvalue_thread_(boost::bind(&Demo::do_calc_in_thread, this)) { } packet_promise_shared_ptr calc() { packet_promise_shared_ptr ptrPromisePacket(new packet_promise()); boost::mutex::scoped_lock l(mymap_mutex_); mymap_.insert(seq_promise_pair(counter_, ptrPromisePacket) ); counter_++; return ptrPromisePacket; } //calculate in a seperate thread and set_value(), loops forever void do_calc_in_thread() { while(true) { { boost::mutex::scoped_lock l(mymap_mutex_); seq_to_promise_map::iterator value_in_map_iter = mymap_.begin(); for (value_in_map_iter; value_in_map_iter != mymap_.end(); value_in_map_iter++) { unsigned long in_counter = value_in_map_iter->first; //printf(""[%d] thread running set value\n"", in_counter); Packet resultPacket(in_counter); value_in_map_iter->second->set_value(resultPacket); //make a copy mymap_.erase(value_in_map_iter); } } } } }; int main(int argc, char** argv) { Demo demo; unsigned long testCounter=0; while(true) { packet_promise_shared_ptr packetPromisePtr = demo.calc(); boost::system_time const timeout = boost::get_system_time() + boost::posix_time::milliseconds(500); boost::unique_future< Packet > pf = packetPromisePtr->get_future(); //often causes core-dump if (!pf.timed_wait_until(timeout)) { printf(""[%d] error \n"", testCounter); break; } else { Packet result = pf.get(); printf(""[%d] ok : %d \n"", testCounter, result.in); } testCounter++; } } }}} " Bugs closed Boost 1.44.0 thread Boost 1.43.0 Showstopper fixed promise thread future lazy_init