【问题标题】:pthread_cond_timedwait ret 22 but errno is successpthread_cond_timedwait ret 22 但 errno 成功
【发布时间】:2017-11-20 14:35:39
【问题描述】:

我正在调用pthread_cond_timedwait,我在其中设置低于超时值

clock_gettime(CLOCK_MONOTONIC, &timeout);
//timeout.tv_sec+= 1;
timeout.tv_nsec+= 100000000;
ret = pthread_cond_timedwait(&Cond, &Mtx, &timeout);

但是,一段时间后我得到了 ret 值 22 但 errno 是成功的。

如果我启用timeout.tv_sec 并注释掉timeout.tv_nsec,那么我看不到任何问题,而且我总是将 ret 值设为零,但反之亦然。

谁能帮我理解为什么pthread_cond_timedwait 返回22 而errno 为零?

【问题讨论】:

    标签: linux pthreads


    【解决方案1】:

    谁能帮我理解为什么 pthread_cond_timedwait 返回 22 而 errno 为零?

    Pthreads 函数可能会也可能不会设置errno 值;它们的返回值代表错误值。您可以将ret 分配给errno 并调用perror()strerror()

    但是,一段时间后我得到了 ret 值 22 但 errno 是成功的。

    你说pthread_cond_timedwait()值的返回值是22(通常是EINVAL),说明问题出在你传递的timeout.tv_nsec值上。

    POSIX manual 说:

    EINVAL
    abstime 参数指定了一个小于零或大于或等于 10 亿的纳秒值。

    既然你这样做了:

    timeout.tv_nsec+= 100000000;
    

    timedout.tv_nsec 很可能已经包含一些值,并且将其添加 1 亿会导致EINVAL。如果上面的代码在一个函数中并且被重复调用,那么在第 10 次调用时,timeout.tv_nsec 将达到 10 亿。建议你确保timeout.tv_nsec小于10亿再试。

    例如,做:

    timeout.tv_nsec = 100000000;
    

    代替:

    timeout.tv_nsec += 100000000;
    

    【讨论】:

      【解决方案2】:

      您的问题是您在未检查溢出的情况下将值添加到纳秒。正确的代码是:

      clock_gettime(CLOCK_MONOTONIC, &timeout);
      timeout.tv_nsec += 100'000'000;
      if(timeout.tv_nsec >= 1'000'000'000)
      {
          timeout.tv_sec += 1;
          timeout.tv_nsec -= 1'000'000'000;
      }
      ret = pthread_cond_timedwait(&Cond, &Mtx, &timeout);
      

      正如 P.P 所提到的,pthread_cond_timedwait() 的返回值是 errno 变量中通常预期的值。我建议您将变量的名称更改为更能代表返回内容的名称(可能是eerr)。

      来自docs

      错误

      pthread_cond_initpthread_cond_signalpthread_cond_broadcastpthread_cond_wait 永远不会返回错误代码。

      pthread_cond_timedwait 函数在出错时返回以下错误代码:

      ETIMEDOUT
      直到abstime指定的超时时间才会发出条件变量的信号

      EINTR
      pthread_cond_timedwait 被信号打断了

      EPERM
      互斥体类型为PTHREAD_MUTEX_ERRORCHECK 或互斥体是健壮的互斥体,当前线程不拥有互斥体。

      pthread_cond_destroy 函数出错时返回以下错误代码:


      一些线程当前正在等待cond

      您经常遇到的另一个错误是EPERM。在大多数情况下,这是因为您的互斥锁或条件未正确初始化,或者当前线程在调用之前没有锁定互斥锁。

      注意:数字中的刻度自 C++11 起有效,如果您的编译器对它们不满意,请将其删除。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-12
        • 1970-01-01
        • 2019-10-13
        • 2019-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多