1

我们有一些代码来爬取堆栈,当我们这样做时能够转储当前时间非常方便。不幸的是,虽然该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信号安全的类似结果?

4

1 回答 1

0

我想出了一个解决这个问题的方法。为信号上下文之外的进程调用localtime不同的线程,并在清除小时/分钟/秒字段后缓存该值(以及mktime该操作的结果struct tm)。

只要我有一个自上次缓存值以来的 24 小时内的值,我就可以在信号处理程序中使用它,通过添加回增量的小时/分钟/秒字段来手动构造处理程序中struct tmgettimeofday从缓存的时间点开始。

它并不完美,并且有一些棘手的方面要确保我在处理程序执行时不会读取正在更新的值,但在大多数情况下我可以避免对事后转储文件进行后处理,并且不会由于信号不安全而陷入或挂起处理程序中的函数。

于 2012-06-29T03:34:32.677 回答