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