xCrash 和 Android 系统处理 Native Crash 流程(即 debuggerd 守护进程)基本一致。
xc_jni#xc_jni_init
static jint xc_jni_init(JNIEnv *env,
jobject thiz,
jint api_level,
jstring os_version,
..) {
// 保存配置参数,获取进程名,创建日志文件夹,
// 预先打开两个文件描述符,防止文件描述符达到上限,无法创建
xc_common_init(api, version...)
if(crash_enable) {
...
// 使用calloc,为需要dump的线程(支持正则配置)数组分配内存
// 例如 "^xcrash\\\\.sample$", "^Signal Catcher$", "^Jit thread pool$"
if(NULL != (c_crash_dump_all_threads_whitelist = calloc(len, sizeof(char *)))) {
...
}
//crash init
r_crash = xc_crash_init(env,
crash_rethrow ? 1 : 0,
(unsigned int)crash_logcat_system_lines,
(unsigned int)crash_logcat_events_lines,
(unsigned int)crash_logcat_main_lines,
crash_dump_elf_hash ? 1 : 0,
crash_dump_map ? 1 : 0,
crash_dump_fds ? 1 : 0,
crash_dump_network_info ? 1 : 0,
crash_dump_all_threads ? 1 : 0,
(unsigned int)crash_dump_all_threads_count_max,
c_crash_dump_all_threads_whitelist,
c_crash_dump_all_threads_whitelist_len);
...
}
return (0 == r_crash && 0 == r_trace) ? 0 : XCC_ERRNO_JNI;
}
xc_crash#xc_crash_init
int xc_crash_init(JNIEnv *env,
int rethrow,
unsigned int logcat_system_lines,
unsigned int logcat_events_lines,
unsigned int logcat_main_lines,
int dump_elf_hash,
int dump_map,
int dump_fds,
int dump_network_info,
int dump_all_threads,
unsigned int dump_all_threads_count_max,
const char **dump_all_threads_whitelist,
size_t dump_all_threads_whitelist_len)
{
xc_crash_prepared_fd = XCC_UTIL_TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
xc_crash_rethrow = rethrow;
if(NULL == (xc_crash_emergency = calloc(XC_CRASH_EMERGENCY_BUF_LEN, 1))) return XCC_ERRNO_NOMEM;
// 获取 nativeLibraryDir 下的 libxcrash_dumper.so
if(NULL == (xc_crash_dumper_pathname = xc_util_strdupcat(xc_common_app_lib_dir, "/"XCC_UTIL_XCRASH_DUMPER_FILENAME))) return XCC_ERRNO_NOMEM;
XCD_LOG_DEBUG("xc_common_app_lib_dir: %s", xc_common_app_lib_dir);
XCD_LOG_DEBUG("xc_crash_dumper_pathname: %s", xc_crash_dumper_pathname);
XCD_LOG_DEBUG("xc_common_api_level: %d", xc_common_api_level);
//init the local unwinder for fallback mode
xcc_unwind_init(xc_common_api_level);
//init for JNI callback
xc_crash_init_callback(env);
//struct info passed to the dumper process
memset(&xc_crash_spot, 0, sizeof(xcc_spot_t));
xc_crash_spot.api_level = xc_common_api_level;
xc_crash_spot.crash_pid = xc_common_process_id;
xc_crash_spot.start_time = xc_common_start_time;
xc_crash_spot.time_zone = xc_common_time_zone;
xc_crash_spot.logcat_system_lines = logcat_system_lines;
xc_crash_spot.logcat_events_lines = logcat_events_lines;
xc_crash_spot.logcat_main_lines = logcat_main_lines;
xc_crash_spot.dump_elf_hash = dump_elf_hash;
xc_crash_spot.dump_map = dump_map;
xc_crash_spot.dump_fds = dump_fds;
xc_crash_spot.dump_network_info = dump_network_info;
xc_crash_spot.dump_all_threads = dump_all_threads;
xc_crash_spot.dump_all_threads_count_max = dump_all_threads_count_max;
xc_crash_spot.os_version_len = strlen(xc_common_os_version);
xc_crash_spot.kernel_version_len = strlen(xc_common_kernel_version);
xc_crash_spot.abi_list_len = strlen(xc_common_abi_list);
xc_crash_spot.manufacturer_len = strlen(xc_common_manufacturer);
xc_crash_spot.brand_len = strlen(xc_common_brand);
xc_crash_spot.model_len = strlen(xc_common_model);
xc_crash_spot.build_fingerprint_len = strlen(xc_common_build_fingerprint);
xc_crash_spot.app_id_len = strlen(xc_common_app_id);
xc_crash_spot.app_version_len = strlen(xc_common_app_version);
xc_crash_init_dump_all_threads_whitelist(dump_all_threads_whitelist, dump_all_threads_whitelist_len);
//for clone and fork
#ifndef __i386__
if(NULL == (xc_crash_child_stack = calloc(XC_CRASH_CHILD_STACK_LEN, 1))) return XCC_ERRNO_NOMEM;
xc_crash_child_stack = (void *)(((uint8_t *)xc_crash_child_stack) + XC_CRASH_CHILD_STACK_LEN);
#else
if(0 != pipe2(xc_crash_child_notifier, O_CLOEXEC)) return XCC_ERRNO_SYS;
#endif
//register signal handler
return xcc_signal_crash_register(xc_crash_signal_handler);
}
xc_crash_prepared_fd
分配一个文件描述符xc_crash_emergency
calloc 分配内存,30kxc_crash_dumper_pathname
为libxcrash_dumper.so
的路径xcc_unwind_init(xc_common_api_level)
,初始化系统 dump 方法,为后续兜底操作xc_crash_init_callback(env)
初始化 NativeHandler#crashCallback
,最后的崩溃信息会回调给 Java 层xc_crash_spot
,传递给 dumper 进程的信息