Glibc更新导致pthread_cond_timedwait失效
话说产品的大哥转过来一个定时器失效的问题,当时还以为是内核的定时器,到手一看,居然是产品代码中的一个自写的定时器没有生效,被告知是调用的系统接口,看着令人头痛的CPP代码,咨询之后才知道是ACE(Adaptive Communication Environment)框架,然后再次被人用小学学到的对比法把问题丢给了自己,苦命的搞了内核还要了解CPP各种框架。
先大致说一下问题:产品用ACE的框架,使用对象cond_timedwait等待设定时间超时,进程运行中,将系统的时间提前一天,cond_timedwait就失效了,1s的超时跑了3小时也没有动静。
可以确定的是cond_timedwait挂住了,通过gdb attach到进程看bt数据,可以看到cond_timedwait其实是封装glibc的pthread_cond_timedwait函数实现的,这个样子就直接跳过了ACE框架的代码(节省了不少脑细胞),根据产品大哥反馈,问题是在某日代码持续集成后出的问题,于是遍历相关修改,发现当时更新了glibc的rpm包,即从glibc-2.11.3-17.39.1更新到glibc-2.11.3-17.43.1,于是将glibc强制回退,OK,问题木有了。
翻看SUSE glibc的更新记录看
- Fix pthread_cond_timedwait stack unwinding (bnc#750741, bnc#777233)
只好找李义童鞋要bugzilla看,说的是为了和posix保持一致,将pthread_cond_timedwait的相对时间改为了绝对时间,同时自己写了段代码验证glibc问题,发现只要提前1min pthread_cond_timedwait就会失效,代码参见如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>
pthread_t thread;
pthread_cond_t cond;
pthread_mutex_t mutex;
int flag = 1;
void *timewait(void *argv)
{
int pthread_times = 0;
struct timeval now;
struct timespec timeout;
pthread_mutex_lock(&mutex);
while(flag)
{
printf("%dn",pthread_times);
gettimeofday(&now, NULL);
printf("now is %ldn", now.tv_sec);
timeout.tv_sec = now.tv_sec + 5;
timeout.tv_nsec = now.tv_usec * 1000;
printf("timeout is %ldn", timeout.tv_sec);
pthread_cond_timedwait(&cond, &mutex, &timeout);
}
pthread_mutex_unlock(&mutex);
printf("thread exitn");
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
if(0 != pthread_create(&thread, NULL, timewait, NULL))
{
printf("create pthread errorn");
return 1;
}
char C;
while((c = getchar()) != 'q');
flag = 0;
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
printf("Wait for thread to exitn");
pthread_join(thread, NULL);
return 0;
}
将如上代码编译,然后线程每5s打印一次,通过date -s "hh:mm"将系统时间提前1min,就发现线程卡死在pthread_cond_timedwait,也就是超时函数失效了。
从SUSE bugzilla上搞到了patch文件,全是汇编......
先跟着问题,具体原因后续再发。
后续:NOVELL根据GNU的posix标志将相对时间改成了绝对时间,这个酱紫就会在timewait等待时间的时候对系统时间产生依赖,改动系统时间就会导致失效。
NOVELL的意见是:这是posix标准,就不支持改时间......
目前看glibc这个问题不会改过来啦,想办法在用户态规避,不建议手工改正,这个样子便脱离了主分支,成为版本控制的蛀虫。
Glibc更新导致pthread_cond_timedwait失效来自于OENHAN
链接为:https://oenhan.com/glibc_pthread_cond_timedwait_disable/