pthread_cond_timedwait 函数返回错误值22(EINVAL)

函数原型:

int pthread_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex, const struct timespec *abstime);

函数描述pthread_cond_timedwait 函数返回错误值22(EINVAL)_第1张图片pthread_cond_timedwait 函数使用说明链接

函数返回值

成功返回0,否则返回一个错误号表示错误信息。
pthread_cond_timedwait 函数返回错误值22(EINVAL)_第2张图片
pthread_cond_timedwait 函数返回错误值22(EINVAL)_第3张图片pthread_cond_timedwait 函数返回错误值22(EINVAL)_第4张图片
Linux System Error 描述链接

问题分析

根据上面信息可以清晰知道,pthread_cond_timedwait 函数调用返回 EINVAL
pthread_cond_timedwait 函数原型我们可以得知,有三个入口参数:

  • pthread_cond_t *cond:条件变量(触发条件)
  • pthread_mutex_t *mutex: 互斥锁
  • const struct timespec *abstime: 等待时间(其值为系统时间 + 等待时间)

在使用 pthread_cond_timedwait 函数时,必须有三步:

  1. 加互斥锁:pthread_mutex_lock(&mutex)
  2. 等待:pthread_cond_timedwait(&cond, &mutex, &abstime) //解锁->等待->加锁
  3. 解互斥锁:pthread_mutex_unlock(&mutex)

项目调用代码如下:

#define HI_COND_TIMEDWAIT_WITH_RETURN(cond, mutex, usec, ret) \
    do {                                                      \
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };   \
        (HI_VOID)clock_gettime(CLOCK_MONOTONIC, &ts);        \
        ts.tv_sec += (usec / 1000000LL);                      \
        ts.tv_nsec += (usec * 1000LL % 1000000000LL);         \
        ret = pthread_cond_timedwait(&cond, &mutex, &ts);     \
    } while (0)

通过对项目代码的分析, 条件变量 cond, 互斥锁 mutex 的使用都符合调用规范,因此猜测传参错误发生在参数 abstime, 而从网上查询信息发现有网友提出 ts.tv_nsec 的值是有限制的,必须小于1s(也就是值不能大于1000000000),参考网友修改对项目代码进行了修改。
(PS:关于ts.tv_nsec 值的限制没有找到相关文档说明,此处依然带着疑问,希望后续可以找到)

修改后代码

#define HI_COND_TIMEDWAIT_WITH_RETURN(cond, mutex, usec, ret) \
    do {                                                      \
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };   \
        (HI_VOID)clock_gettime(CLOCK_MONOTONIC, &ts);         \
        ts.tv_sec += (usec / 1000000LL);                      \
        ts.tv_nsec += (usec * 1000LL % 1000000000LL);         \
        if (ts.tv_nsec > 1000000000) {                        \
        	ts.tv_sec += 1;                                   \
        	ts.tv_nsec -= 1000000000;                         \
        }                                                     \
        ret = pthread_cond_timedwait(&cond, &mutex, &ts);     \
    } while (0)

线程等待和唤醒函数比较

sleep 线程等待,等待期间线程无法唤醒
pthread_cond_wait 线程等待信号触发,如果没有信号触发,无限期等待下去。
pthread_cond_timedwait 线程等待一定的时间,如果超时或有信号触发,线程唤醒。

心得总结

关于 pthread_cond_timedwait 函数返回 EINVAL 的信息,在项目期间在调试信息中就已经发现了,但由于当时机器简单运行无异常和本人的侥幸心理,没引起重视,没深究错误原因,以至于到产品测试阶段进行长时间运行时出现了异常停止问题,因此为了告诫自己,写下了此文!

细节决定成败!
致广大而尽精微,极高明而道中庸。

你可能感兴趣的:(Linux,工作总结,C,语言学习)