How to use backtrace() safely in signal handler.

Paul Guo
Thu Dec 5 13:16:00 GMT 2019


I know it is Async signal unsafe per

Function: int backtrace (void **buffer, int size)

Preliminary: | MT-Safe | AS-Unsafe init heap dlopen plugin lock | AC-Unsafe
init mem lock fd | See POSIX Safety

but I want to know how unsafe it is and see if I could use that safely in
signal handler with some limitations.

I found the explanation of those words like "heap", "dlopen", etc from

But is still a bit confusing. So I have some questions as below,

1. what is "init" in the AS-Unsafe words? It is not explained in the above

2. heap

The doc says "Functions marked with heap may call heap memory management
functions from the malloc/free family of functions and are only as safe as
those functions"

backtrace() trigger malloc() only when dynamically loading libgcc. Does
that mean if libgcc was preloaded in the application we do not need to
worry about that?

And it looks like for glibc with that patch we do not even need to worry
about the 'heap' case. Am I correctly understanding?

2. dlopen: preloading libgcc could work around this limitation, right?

3. plugin: I do not know how backtrace() is affected by this but it seems
that it does not affect backtrace()?

4. lock: I've seen a self deadlock (in backtrace()) case in my environment
(backtrace()-ing in one signal handler and then gets another signal and
that signal handler calls backtrace() again). The lock should
be __gthread_mutex_lock. For this we could use a wrapper of backtrace() to
prevent reentrance of backtrace() to work around this issue (Yes of course
the final backtrace() will return nothing but this scenario is rare so it
should be fine, right?).


More information about the Libc-help mailing list