async_safe_fatal() calls abort() at the end, which can be intercepted by a custom SIGABRT handler.
In particular, crashlytics installs such a handler and tries to fork() after catching SIGABRT.
hardened_malloc uses pthread_atfork() to register fork handlers. These handlers try to lock internal
hardened_malloc mutexes. If at least one of those mutexes is already locked, which is usually the
case, thread that called fatai_error() gets deadlocked, while the other threads (if there are any)
continue to run.
async_safe_fatal() performs the following steps:
- logs the error message to stderr and logcat
- passes error message to debuggerd via android_set_abort_message(). debuggerd then saves the error
message in the crash report file ("tombstone")
- calls abort()