【问题标题】:boost - timed_wait does not waitboost - timed_wait 不等待
【发布时间】:2015-07-29 08:43:34
【问题描述】:

我在 Linux OS + ARM 处理器 + boost 1.51 上运行以下代码。但是,代码没有按预期工作,timed_wait() 调用立即返回。

#include <boost/thread/condition.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

using namespace std;

int main()
{
     boost::mutex mutex_;
     boost::mutex::scoped_lock lock( mutex_ );

     boost::xtime xt;
     boost::condition condition;

     // wait for one second or wait on lock
     boost::xtime_get(&xt, boost::TIME_UTC_);

     xt.sec += 1;

     cout << "Before 1 second wait" << endl;
     condition.timed_wait(lock, xt);
     cout << "After 1 second wait" << endl;

     return 0;
}

在具有相同 ARM 处理器但不同版本的 Linux + glibc + 相同的 boost 1.51 库的其他系统上,代码运行正常并等待 1 秒。

我尝试使用 strace 调试问题。我发现 futex() 的调用不是在它不工作的系统中进行的。

strace 来自代码正在运行的系统:

write(1, "Before 1 second wait\n", 21Before 1 second wait)  = 21
futex(0xb6fbf0dc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
clock_gettime(CLOCK_REALTIME, {1438150496, 732211544}) = 0
futex(0xbef07a44, FUTEX_WAIT_PRIVATE, 1, {0, 998193456}) = -1 ETIMEDOUT (Connection timed out)
futex(0xbef07a28, FUTEX_WAKE_PRIVATE, 1) = 0
write(1, "After 1 second wait\n", 20After 1 second wait)   = 20

strace 来自代码不工作的系统:

    write(1, "Before 1 second wait\n", 21Before 1 second wait)  = 21
    futex(0xb6fc90dc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
    clock_gettime(CLOCK_REALTIME, {1438150407, 134963583}) = 0
    futex(0xbe9be988, FUTEX_WAKE_PRIVATE, 1) = 0
    write(1, "After 1 second wait\n", 20After 1 second wait)   = 20

是否需要对内核/glibc 进行更改才能使此代码正常工作?

【问题讨论】:

  • 尝试predicate 版本的 timed_wait。可能是虚假唤醒迫使早起。 condition.timed_wait(lock, boost::posix_time::milliseconds(1000), f); 其中f 定义为bool f(void) { return false; }
  • 感谢您的建议。但是,谓词没有帮助。我认为,正如我在问题中提到的那样,由于某种原因没有进行较低级别的 futex() 调用。
  • 嗯,您的 Boost 安装似乎由于某种原因损坏了。它的行为“好像”它发现超时已经过去,因此无需调用futex 等待条件。您可以跟踪boost::xtime_get() 调用,查看它返回的时间戳,并将其与clock_gettimecondition.timed_wait() 调用返回的时间戳进行比较。

标签: c++ boost linux-kernel futex


【解决方案1】:

与其在使用超时时搞砸时钟,不如使用实际的超时?

condition.timed_wait(lock,boost::posix_time::milliseconds(1000))

这可以防止各种奇怪的问题。

【讨论】:

  • timed_wait 调用采用绝对值的时间,直到它将等待。其实我试过你的建议,结果是一样的。
【解决方案2】:

通过将超时时间从 1 更改为 100,我能够弄清楚发生了什么。

我将超时作为参数传递给程序并使用

xt.sec += timeout;

当超时时间超过 26 时,程序正在等待 (timeout - 26) 秒。也就是说,程序等待1秒:如果超时为27,2秒:如果超时为28,以此类推……

偏移量 26 来自闰秒数。如果系统上的时区信息包含闰秒信息,那么,我们就会看到这个问题。如果我将时区信息 (/etc/localtime) 更改为指向没有闰秒信息的 zoneinfo 文件,那么 boost API 可以正常工作。

【讨论】:

  • 我发现了非常相似的 SO 问题:stackoverflow.com/questions/2784639/…。它的作者在 RedHat 上遇到了与 boost 1.38 相同的问题。实际上,Boost 文档指出,将 UTC 时间用于 future 时间戳并不是一个好主意:正是因为闰秒。 boost::chrono::seconds(1) 似乎更适合超时间隔。
  • 感谢您的评论和 chrono 类的使用。当我第一次发布查询时,我没有意识到这是一个闰秒问题。
猜你喜欢
  • 2020-07-03
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多