Запуск процесса отладки
Q: Как я отлаживаю код запуска процесса?
A: Это зависит от того, как запускается процесс. Для типичного процесса прикладного уровня можно отладить код запуска путем запуска его из отладчика в XCode. Однако могут быть обстоятельства, где это не опция. Например:
если проблема маскируется путем запущения приложения в отладчике
если программа не является типовым приложением (например, это мог бы быть фильтр CUPS),
Следующие разделы описывают различные способы отладить код запуска процесса.
Запишите код для остановки
Если можно создать программу из источника, это тривиально для добавления кода для остановки программы в первой строке основного. Перечисление 1 показывает пример этого.
Код перечисления 1 для остановки при запуске
#include <signal.h> #include <unistd.h> int main(int argc, char **argv) { (void) raise(SIGSTOP); /// rest of your code here } |
Это отправляет a SIGSTOP к процессу, останавливающему его выполнение так, чтобы можно было присоединить использование GDB. Также можно возобновить выполнение путем отправки процесса a SIGCONT использование уничтожает.
launchd
Если не удобно создать программу из источника, можно использовать множество других методов. Если Вашей программой управляют launchd, можно добавить WaitForDebugger свойство к Вашему файлу списка свойств для имения launchd остановите свою программу перед ним, это выполняет единственную инструкцию. См. страницу справочника для подробных данных.
GDB
Если Вашей программой не управляют launchd, можно использовать GDB's --waitfor опция. GDB опросит список процессов, ожидающий процесса соответствия, который будет запущен. Можно предоставить опцию или на командной строке или как параметр GDB's attach команда.
Факт, что GDB опрашивает список процессов, имеет два недостатка. Во-первых, это использует много CPU при ожидании процесса, который будет запущен. Во-вторых, программа останавливается в неопределенном состоянии. При работе Mac OS X 10.5 или позже, вероятно, лучше использовать DTrace вместо этого.
DTrace
Перечисление 2 показывает примеру сценарий DTrace, устанавливающий зонд на обычно используемом системном вызове (getpid) и, когда тот зонд поражен, останавливает процесс и вызывает GDB на него. Перечисление 3 показывает пример своего использования.
Перечисление 2 WaitAttach.d
#! /usr/sbin/dtrace -w -q -s
syscall::getpid:entry
/ execname == $$1 /
{
stop();
system(
"echo attach %d > /tmp/WaitAttach.gdb ; gdb -x /tmp/WaitAttach.gdb",
pid
);
exit(0);
} |
Перечисление 3 Используя WaitAttach.d
$ # Make the script executable $ chmod ugo+x WaitAttach.d $ # Run it $ sudo ./WaitAttach.d TextEdit GNU gdb 6.3.50-20050815 [...] [... now launch TextEdit ...] Attaching to process 3723. Reading symbols for shared libraries . done 0x8fe21a25 in __dyld_getpid () (gdb) bt #0 0x8fe21a25 in __dyld_getpid () #1 0x8fe07139 in __dyld__ZN4dyld5_mainEPK11mach_headermiPPKcS5_S5_ () #2 0x8fe01872 in __dyld__ZN13dyldbootstrap5startEPK11mach_headeriPPKcl () #3 0x8fe01037 in __dyld__dyld_start () |
Можно изменить этот сценарий для удовлетворения определенных потребностей. Например:
Сценарий устанавливает зонд на
getpid, который в настоящее время является первым системным вызовом, сделанным процессом. Можно изменить это на любой другой системный вызов (путем изменения «getpid» к чему-то еще), или соответствовать все системные вызовы (путем удаления «getpid» полностью).Сценарий в настоящее время соответствует процесс своим исполнимым именем. Это - точное строковое соответствие. Можно использовать нечеткое соответствие путем вызова функций DTrace как
strstr.Можно также расширить соответствие для поиска других критериев. Например, можно использовать DTrace, созданный в переменной
ppidотфильтровать на родительском процессе ID.Как есть сценарий выполняет GDB как корень. Если это - проблема, можно изменить сценарий для вызова chroot команды для установки пользователя и группы ID GDB к тому, чего Вы желаете.
История версии документа
| Дата | Примечания |
|---|---|
| 21.12.2007 | Новый документ, описывающий методы для отладки кода запуска процесса. |