Как OS X генерирует отчет о сбое? - PullRequest
4 голосов
/ 13 февраля 2012

Материал, доступный из Интернета, списка рассылки, таких книг, как Mac OS X Internals , и даже исходный код весьма ограничен.

Теперь я знаю, что ядро ​​xnu вызывает EXC_CRASHкоторый запускается для запуска «Problem Reporter.app» (ранее Crash Reporter.app).Использует ли это приложение какой-либо интерфейс отладки для генерации отчета о сбое, или ядро ​​уже генерирует отчет и просто уведомляет приложение, чтобы открыть уже сгенерированный отчет?

1 Ответ

9 голосов
/ 23 сентября 2012

Каждый поток Маха и / или задача (базовый объект ядра, поверх которого реализован процесс уровня BSD) имеет порты исключений. Доступны три уровня портов: Поток, Задача и Хост. Когда возникает исключение, сообщение Маха отправляется - сначала в порт потока, затем - если никто его не перехватил - в задаче и, наконец, в хост. Если вы получаете порт, вы можете перехватить исключение, отладить его (как это делает GDB в OS X) или сгенерировать аварийный дамп (как это делает Crash Reporter). В частности, launchd - родитель всех системных задач OS X - регистрирует их порты исключений, поэтому он получает сообщения и затем запускает CrashReporter (как вы можете видеть из списка ReportCrash launchd:

 <key>MachServices</key>
        <dict>
                <key>com.apple.ReportCrash.DirectoryService</key>
                <dict>
                        <key>DrainMessagesOnCrash</key>
                        <string>All</string>
                        <key>ExceptionServer</key>
                        <dict/>
                </dict>
        </dict>

Код ядра XNU отвечает за отправку сообщения в EXC_CRASH. В частности, proc_prepareexit делает это:

  /* If a core should be generated, notify crash reporter */
        if (hassigprop(WTERMSIG(rv), SA_CORE) || ((p->p_csflags & CS_KILLED) != 0)) {
                /* 
                 * Workaround for processes checking up on PT_DENY_ATTACH:
                 * should be backed out post-Leopard (details in 5431025).
                 */
                if ((SIGSEGV == WTERMSIG(rv)) && 
                                (p->p_pptr->p_lflag & P_LNOATTACH)) {
                        goto skipcheck;
                }

                /*
                 * Crash Reporter looks for the signal value, original exception
                 * type, and low 20 bits of the original code in code[0] 
                 * (8, 4, and 20 bits respectively). code[1] is unmodified. 
                 */
                code = ((WTERMSIG(rv) & 0xff) << 24) |
                        ((ut->uu_exception & 0x0f) << 20) | 
                        ((int)ut->uu_code & 0xfffff);
                subcode = ut->uu_subcode;
                (void) task_exception_notify(EXC_CRASH, code, subcode); // <-- Sends the msg
        }
...