#5034 closed Bugs (worksforme)
boost::this_thread::sleep either returns instantaneously or spins
Reported by: | Jamie Allsop | Owned by: | Anthony Williams |
---|---|---|---|
Milestone: | To Be Determined | Component: | thread |
Version: | Boost 1.45.0 | Severity: | Showstopper |
Keywords: | Cc: | cnewbold@… |
Description
From the docs I'd expect to be able to write this:
std::cout << "Time Before Sleep: " << boost::posix_time::microsec_clock::local_time() << std::endl; boost::this_thread::sleep( boost::posix_time::seconds(10) ); std::cout << "Time After Sleep : " << boost::posix_time::microsec_clock::local_time() << std::endl;
and have the 'this' thread sleep for approximately 10 seconds. Instead sleep returns instantaneously:
Time Before Sleep: 2010-Dec-25 01:38:50.949160000 Time After Sleep : 2010-Dec-25 01:38:50.949436000
I've tried this with boost 1.45 and boost 1.43 using gcc 4.4 on debian x86_64. This used to work for me on 32-bit debian unstable using gcc 4.3.
In addition to sleep returning instantaneously (happens every time) I have observed with more complex scenarios involving multiple threads sleep enter a busy spin, never returning (process needs killed). I am trying to create a minimal test case for this.
Rather obviously the code where this hits is here in source:/boost/tags/release/Boost_1_45_0/libs/thread/src/pthread/thread.cpp
void sleep(const system_time& st) { detail::thread_data_base* const thread_info=detail::get_current_thread_data(); if(thread_info) { unique_lock<mutex> lk(thread_info->sleep_mutex); while(thread_info->sleep_condition.timed_wait(lk,st)); } else { xtime const xt=get_xtime(st); for (int foo=0; foo < 5; ++foo) { # if defined(BOOST_HAS_PTHREAD_DELAY_NP) timespec ts; to_timespec_duration(xt, ts); BOOST_VERIFY(!pthread_delay_np(&ts)); # elif defined(BOOST_HAS_NANOSLEEP) timespec ts; to_timespec_duration(xt, ts); // nanosleep takes a timespec that is an offset, not // an absolute time. nanosleep(&ts, 0); # else mutex mx; mutex::scoped_lock lock(mx); condition cond; cond.timed_wait(lock, xt); # endif xtime cur; xtime_get(&cur, TIME_UTC); if (xtime_cmp(xt, cur) <= 0) return; } } }
Specifically something appears to go wrong here:
if(thread_info) { unique_lock<mutex> lk(thread_info->sleep_mutex); while(thread_info->sleep_condition.timed_wait(lk,st)); }
I came across this while writing a test for something else and so have not been able to follow up in any more detail yet at this time.
Change History (8)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
Cc: | added |
---|
comment:3 by , 12 years ago
I should add here that I tried this with a debug build of boost thread and could not get any better back trace. I also suspect this is a 64-bit only problem since others have reported no issues on 32-bit builds.
comment:4 by , 12 years ago
Resolution: | → worksforme |
---|---|
Status: | new → closed |
I cannot reproduce this problem on 64-bit Ubuntu 10.10
comment:5 by , 12 years ago
Similar problem was described here http://lists.boost.org/boost-users/2010/10/63635.php I can reproduce it easily on Linux.
comment:6 by , 12 years ago
Can you be more specific about how you reproduce this on Linux? What compile flags you use and on what distribution and architecture? I think this ticket clearly needs re-opened.
comment:7 by , 11 years ago
I see the same exact problem on ubuntu 32bit, on virtualbox (mac host), but it happens ONLY when I run the program in gdb.
Spawning 4 thread, each one cycling and sleeping for up to one second between any cycle, I always get 1 or 2 threads that never exit from the sleep.
Part of code:
... cout << "Updater started with id " << boost::this_thread::get_id() << endl; while (true) { /* do things */ // Throttle elapsed = boost::posix_time::microsec_clock::universal_time() - this->last_update; sleep_for = interval - elapsed; cout << boost::this_thread::get_id() << " sleeping for " << sleep_for << endl; boost::this_thread::sleep(sleep_for); cout << boost::this_thread::get_id() << " sleeped for " << sleep_for << endl; } ...
I get on console:
Updater started with id 0x8090198 Updater started with id 0x8090810 0x8090198 sleeping for 0x8090810 sleeping for 00:00:00.998689 00:00:00.997377 Updater started with id 0x8090fb0 0x8090fb0 sleeping for 00:00:00.998187 Updater started with id 0x8091378 0x8091378 sleeping for 00:00:00.998543 0x8090198 sleeped for 00:00:00.997377 0x8090198 sleeping for 00:00:00.999980 0x8090810 sleeped for 00:00:00.998689 0x8090810 sleeping for 00:00:00.999979 0x8091378 sleeped for 00:00:00.998543 0x8091378 sleeping for 00:00:00.999979 0x8090198 sleeped for 00:00:00.999980 0x8090198 sleeping for 00:00:00.999948 0x8090810 sleeped for 00:00:00.999979 0x8090810 sleeping for 00:00:00.999951 0x8091378 sleeped for 00:00:00.999979 0x8091378 sleeping for 00:00:00.999958
( 0x8090fb0 is blocked )
comment:8 by , 11 years ago
I think this thread: http://lists.boost.org/boost-users/2011/07/69287.php may also describe behaviour that is indirectly related to this issue.
When I see the 'spinning' I can grab the following back trace - which doesn't say much but points to the issue being in the
timed_wait()
, see frame 3.I still don't have a small enough test case to post but thought at least the back trace would help. To summarise then it seems that there is an issue with the
timed_wait()
. Either I see it return immediately or spin.It should also be noted that the call to
boost::this_thread::sleep()
occurs once only in a single thread, in my case the main thread.