您的位置:首页 > 其它

boost::this_thread::sleep_for()死锁

2013-09-24 17:41 267 查看
boost::this_thread::sleep_for()会死锁

(金庆的专栏)

发现睡眠1ms很容易死锁。
boost::this_thread::sleep_for(boost::chrono::milliseconds(1)).

Boost 1.54.0

以下代码很可能重现死锁:

#include "stdafx.h"

#include <iostream>
#include <boost/thread.hpp>

using namespace std;

void worker()
{
for (int i = 0; i < 10000; i++)
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
}

int _tmain(int argc, _TCHAR* argv[])
{
boost::thread_group tg;
for (int i = 0; i < 30; i++)
tg.create_thread(worker);

tg.join_all();
cout << "All done!" << endl;
return 0;
}

附加到死锁进程调试时,调用栈如下:
boost::this_thread::interruptible_wait() Line 547
boost::detail::basic_cv_list_entry::wait() Line 94
boost::detail::basic_condition_variable::do_wait<>() Line 228
boost::condition_variable::wait_until<>() Line 371
boost::this_thread::sleep_until<>() Line32
boost::this_thread::sleep_for<>() Line72
worker()
boost::detail::thread_data<>()

程序在停在thread.cpp:547:
unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count, handles, false, using_timer?INFINITE:time_left.milliseconds);
其中
handle_count = 2
using_timer = false
time_left.milliseconds = 0xfffffffe

发现 basic_cv_list_entry::wait(timeout abs_time) 当 abs_time.milliseconds = uint64(-1) 时就会死锁.
所在可以在此断点,将 abs_time.milliseconds 改为 uint64(-1),就可以重现死锁了.

实际上该参数很可能输入为-1:
wait_until(...)
{
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
...
}

这几天改服务器代码,添加了许多 sleep_for(), 结果就经常发现服务器停止响应了。
幸好该错误仅在Windows上存在。错误位于 boost/thread/win32/condition_variable.hpp.

正准备给Boost添加条Bug记录,发现该错误已在3周前报告,10天前已修正,将在1.55.0版本中发布。
见:
Condition variable will wait forever for some timepoint values (MSVC) https://svn.boost.org/trac/boost/ticket/9079
修正代码如下:

chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: