前段时间我们发现在信号处理函数中使用localtime()函数可能会导致进程死锁。但一直没有找到解决此问题的方法,也没有找到产生此问题的根源。最近我考虑使用pthread_mutex来包装一次localtime()函数,达到安全使用localtime()函数的目的。在测试中发现,使用pthread_mutex并不能达到预期的设想。
我把localtime()相关的代码全部删除,发现问题依旧。可见这个问题是
pthread_mutex产生的。流程如下:
由此推测,localtime()也有类似的机制。查看glibc的代码发现localtime()也是使用了pthread_mutex来解决线程间同步的问题。如下:
time/localtime.c文件中,
localtime() 调用了
__tz_convert()。
time/tzset.c文件中,
__tz_convert()函数中,
__libc_lock_lock()函数对
tzset_lock变量执行了
lock操作。
sysdeps/pthread/bits/libc-lock.h文件中,定义了一个宏:
#define __libc_lock_lock(NAME) \
(__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
到此处,真相大白:localtime也是使用了pthread_mutex_lock() 来完成互斥调用的功能的。
解决方法:
1) 如果不需要日期,只使用时间时,调用公司标准库中的
GetTime()。
2) 尽量不在信号处理函数中使用
localtime()函数。
3) 当需要使用
localtime()函数时,调用公司标准库中的
GetDate()。
4) 公司标准库使用
pthread_mutex_trylock()来避免死锁;但可能获取时间失败。
其它:
glibc库中可能存在大量函数跟localtime()一样使用了pthread_mutex,可能导致信号处理函数死锁,我们无法一一列举。只能在信号处理函数中包含尽量少的代码,极少调用任何函数,来避免死锁的发生。
此问题在多线程、多进程条件下都不会发生。