Каждый поток и/или задача Mach (основной объект ядра, поверх которого выполняется процесс уровня BSD) имеют порты исключений. доступны три уровня порта: поток, задача и хост. Когда возникает исключение, сообщение Маха отправляется - сначала в порт потока, затем - если никто не поймал его - задачу «И» и, наконец, узел. Если вы получите порт, вы можете поймать исключение, отладить его (как и gdb в OS X) или создать сбой аварийной ситуации (как и Crash Reporter). В частности, запуск программ - родитель всех системных задач OS X - регистрирует свои порты исключения, поэтому он получает сообщения, а затем запускает CrashReporter (как вы можете видеть из ReportCrash PLIST на запуск программ по:
<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
}