我们有一些代码要抓取堆栈,并且能够在我们这样做时转储当前时间非常方便。不幸的是,虽然localtime_r()
函数是可重入的,但它不是信号安全的,我们看到它在某些平台上调用内部pthread互斥函数:
0: c000000000436b90 : __ksleep() + 0x30 (/usr/lib/hpux64/libc.so.1)
1: c000000000152060 : __spin_lock_spin() + 0x1b0 (/usr/lib/hpux64/libpthread.so.1)
2: c0000000001d3da0 : __pth_bound() + 0x160 (/usr/lib/hpux64/libpthread.so.1)
3: c0000000001d9080 : __mxn_wakeup() + 0x140 (/usr/lib/hpux64/libpthread.so.1)
4: c0000000001429a0 : __pthread_mutex_unlock_ng() + 0x940 (/usr/lib/hpux64/libpthread.so.1)
5: c000000000142040 : pthread_mutex_unlock() + 0x20 (/usr/lib/hpux64/libpthread.so.1)
6: c000000000458370 : __thread_mutex_unlock() + 0xb0 (/usr/lib/hpux64/libc.so.1)
7: c000000000321cd0 : __localtime_r_posix() + 0x7e0 (/usr/lib/hpux64/libc.so.1)
我们可以通过调用gettimeofday()
安全地转储时间(省略“通过后续localtime_r()
调用的时间的漂亮打印”)然后处理堆栈跟踪文件。有一些困难有了这个想法,如果可能的话,尽量避免这样做。
不需要在信号处理程序之外进行后处理,是否有任何已知的其他方法来实现信号安全的localtime
类似结果?
答案 0 :(得分:0)
我想出了解决这个问题的方法。在信号上下文之外的进程的不同线程中调用localtime
,并在清除小时/分钟/秒字段后缓存该值(以及该被操纵的mktime
的{{1}}结果)
只要我在上一个缓存值后的24小时内有一个值,我就可以在信号处理程序中使用它,为处理程序中的struct tm
手动构建struct tm
从缓存的时间点开始在小时/分钟/秒字段中添加增量。
它并不完美,并且确保我不会在处理程序执行时读取正在更新的值时有一些棘手的方面,但我可以避免在大多数情况下对post mortem dump文件进行后处理,而不是陷阱或挂起到期在处理程序中发出不安全函数的信号。