2012-02-13 6 views
3

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

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

ответ

7

Каждый поток и/или задача 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 
     }