static kern_return_t mach_exception_callback()

in Source/PLCrashReporter.m [260:323]


static kern_return_t mach_exception_callback (task_t task, thread_t thread, exception_type_t exception_type, mach_exception_data_t code, mach_msg_type_number_t code_count, void *context) {
    plcrashreporter_handler_ctx_t *sigctx = context;
    plcrash_log_signal_info_t signal_info;
    plcrash_log_bsd_signal_info_t bsd_signal_info;
    plcrash_log_mach_signal_info_t mach_signal_info;
    plcrash_error_t err;

    /* Let any other registered server attempt to handle the exception */
    if (PLCrashMachExceptionForward(task, thread, exception_type, code, code_count, &sigctx->port_set) == KERN_SUCCESS)
        return KERN_SUCCESS;
    
    /* Set up the BSD signal info */
    siginfo_t si;
    if (!plcrash_async_mach_exception_get_siginfo(exception_type, code, code_count, CPU_TYPE_ANY, &si)) {
        PLCF_DEBUG("Unexpected error mapping Mach exception to a POSIX signal");
        return KERN_FAILURE;
    }

    bsd_signal_info.signo = si.si_signo;
    bsd_signal_info.code = si.si_code;
    bsd_signal_info.address = si.si_addr;

    signal_info.bsd_info = &bsd_signal_info;
    
    /* Set up the Mach signal info */
    mach_signal_info.type = exception_type;
    mach_signal_info.code = code;
    mach_signal_info.code_count = code_count;
    signal_info.mach_info = &mach_signal_info;
    
    /* Write the report */
    struct mach_exception_callback_live_cb_ctx live_ctx = {
        .sigctx = sigctx,
        .crashed_thread = thread,
        .siginfo = &signal_info
    };
    if ((err = plcrash_async_thread_state_current(mach_exception_callback_live_cb, &live_ctx)) != PLCRASH_ESUCCESS) {
        PLCF_DEBUG("Failed to write live report: %d", err);
        return KERN_FAILURE;
    }

    /* Call any post-crash callback */
    if (crashCallbacks.handleSignal != NULL) {
        /*
         * The legacy signal-based callback assumes the availability of a ucontext_t; we mock
         * an empty value here for the purpose of maintaining backwards compatibility. This behavior
         * is defined in the PLCrashReporterCallbacks API documentation.
         */
        ucontext_t uctx;
        _STRUCT_MCONTEXT mctx;
        
        /* Populate the mctx */
        plcrash_async_memset(&mctx, 0, sizeof(mctx));

        /* Configure the ucontext */
        plcrash_async_memset(&uctx, 0, sizeof(uctx));
        uctx.uc_mcsize = sizeof(mctx);
        uctx.uc_mcontext = &mctx;
    
        crashCallbacks.handleSignal(&si, &uctx, crashCallbacks.context);
    }

    return KERN_FAILURE;
}