话说产品的大哥转过来一个定时器失效的问题,当时还以为是内核的定时器,到手一看,居然是产品代码中的一个自写的定时器没有生效,被告知是调用的系统接口,看着令人头痛的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就会失效,代码参见如下:

将如上代码编译,然后线程每5s打印一次,通过date -s "hh:mm"将系统时间提前1min,就发现线程卡死在pthread_cond_timedwait,也就是超时函数失效了。

从SUSE bugzilla上搞到了patch文件,全是汇编......

先跟着问题,具体原因后续再发。

后续:NOVELL根据GNU的posix标志将相对时间改成了绝对时间,这个酱紫就会在timewait等待时间的时候对系统时间产生依赖,改动系统时间就会导致失效。

NOVELL的意见是:这是posix标准,就不支持改时间......

目前看glibc这个问题不会改过来啦,想办法在用户态规避,不建议手工改正,这个样子便脱离了主分支,成为版本控制的蛀虫。


Glibc更新导致pthread_cond_timedwait失效来自于OenHan

链接为:http://oenhan.com/glibc_pthread_cond_timedwait_disable

发表评论