Question

We've got some code to do crawl the stack, and it's very handy to be able to dump the current time when we do so. Unfortunately, while the localtime_r() function is reentrant, it is not signal safe, and we see it calling internal pthread mutex functions on some platforms:

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)

We can dump the time safely by calling just gettimeofday() (omitting the "pretty-printing of the time with the followup localtime_r() call) and then post processing the stack trace file. There are some difficulties with that idea, and it would be nice to avoid that if possible.

Without requiring post-processing outside of the signal handler, are there any known other ways to achieve a localtime like result that are signal safe?

Was it helpful?

Solution

I came up with a workaround for this problem. Call localtimein a different thread for the process outside of a signal context and cache the value after clearing the hour/min/sec fields (along with the mktime result for that manipulated struct tm).

As long as I have a value from within the 24 hour period since the last cached value, I can consume it in the signal handler, manually constructing a struct tm for the gettimeofday in the handler by adding back in the hour/min/sec fields for the delta from the cached point in time.

It's not perfect, and there's some tricky aspects to ensuring I don't read a value that's being updated while the handler executes, but I can avoid post processing the post mortem dump file in most cases, and not trap or hang due to signal unsafe functions in the handler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top