Xcode покидает зомби-процессы после запуска iOS-тестов / симулятора
После работы в Xcode над приложением для iOS в течение нескольких дней я заметил, что существует более 100 процессов зомби. Похоже, что по одному на каждый раз, когда я запускал модульные тесты, и, возможно, по одному на каждый раз, когда я запускал полное приложение в симуляторе. Вот пример (очищенный и усеченный):
> ps -efj | grep $PRODUCT_NAME
502 2794 236 0 Wed12AM ?? 0:00.00 (MyProduct) me 2794 0 1 Z ??
502 2843 236 0 Wed01AM ?? 0:00.00 (MyProduct) me 2843 0 1 Z ??
502 2886 236 0 Wed01AM ?? 0:00.00 (MyProduct) me 2886 0 1 Z ??
...
502 13711 236 0 Thu11PM ?? 0:00.00 (MyProduct) me 13711 0 1 Z ??
502 13770 236 0 Thu11PM ?? 0:00.00 (MyProduct) me 13770 0 1 Z ??
502 14219 236 0 10:35AM ?? 0:00.00 (MyProduct) me 14219 0 1 Z ??
502 14280 236 0 10:38AM ?? 0:00.00 (MyProduct) me 14280 0 1 Z ??
Z в столбце от второго до последнего указывает, что это процессы зомби. 236 в третьем столбце - это родительский PID, принадлежащий моему пользователю. launchd
в этом случае.
Обратите внимание, что некоторым процессам несколько дней. В течение этого периода времени я несколько раз закрывал и снова открывал Xcode.
Кто-нибудь знает, почему это происходит, или это должно быть причиной для тревоги?
2 ответа
Они не особенно занимают много места.
Похоже, что это артефакт механизма XCode, неправильно убивающего подпроцессы.
У меня та же проблема, но я отмечаю, что в моем случае зомби относятся к ppid 271, который является вызовом launchd под моим именем, а не всей системы.
Мне любопытно, что может случиться, если я убью этот процесс.
В любом случае, выход, вероятно, очистит зомби. И, конечно, перезагрузка будет, но этого следует избегать, в моей книге.
О, это пошло довольно плохо. Не убивайте свой launchd, он бесцеремонно убивает ваш сеанс, но ничего не делает, чтобы вы могли вернуть его обратно, как, например, экран входа в систему.
Мне придется посмотреть и увидеть, что я оставил зомби из-за остановки Xcode. Кажется, здесь может быть пара глупых вещей. Если ваш процесс не ждет ребенка, он становится зомби. Если родитель умирает, я думаю, что следующая вещь в очереди получает его, что в данном случае запускается. Launchd должен ждать () этого, но может быть, это запутывается?
После некоторых особенно тяжелых сессий Xcode, где мой MBP звучал так, как будто его просили выполнить процедуру инициализации STARNET, я решил потратить несколько минут на изучение этой бессмыслицы зомби-процесса... в конце концов, Unix-бокс, который не может быть разветвлен, бесполезная коробка Unix. У меня могут быть хорошие новости. Надеюсь, посмотрим. Запуск Xcode 4.6 на 10.8.2 здесь.
Похоже, что проблема зомби возникает независимо от использования GDB или LLDB. Приложение, работающее в симуляторе, принадлежит процессу отладки - либо GDB, либо "debugserver" в случае LLDB. Когда вы нажимаете "Стоп", процесс приложения, запущенный в симуляторе, превращается в зомби. Это звучит как нечистая последовательность выключения.
Я догадался, что вместо того, чтобы нажать "Стоп", я приостановил приложение, а в консоли отладки (в моем случае LLDB) я отсоединил приложение от запущенного приложения, используя "процесс отсоединения". Быстрый ps проверяет, что отладочный сервер больше не работает... пока все хорошо! Теперь приложение все еще работает в самом симуляторе, но не в режиме отладки. На самом деле, нажать кнопку "Стоп" теперь нельзя.
В симуляторе нажмите кнопку "Домой", чтобы вернуться на трамплин, затем дважды нажмите кнопку "Домой" и вручную закройте приложение. Иди в командную строку и ищи зомби... не зомби! Ура.
Итак... следующий шаг - посмотреть, есть ли разумный способ выполнить эту или аналогичную процедуру выключения через скрипт на python и т. Д. Конечно, это не поможет, если вы находитесь на GDB. Если я могу выполнить чистое отключение с помощью одной команды консоли отладки, тогда нужно просто привыкнуть не нажимать на сломанную кнопку "Стоп". Может быть, есть хак ресурса, чтобы отключить его вообще...:)
РЕДАКТИРОВАТЬ #1: пару интересных лакомых кусочков...
1.) Нажатие кнопки "Стоп" в xcode просто убивает процессы отладки и приложения - нет никаких попыток полностью завершить работу. Отладка printf в делегате приложения applicationWillTerminate и applicationDidEnterBackground показывает, что работающее приложение убито с предубеждением - в консоли не отображаются NSLogs.
2.) В консоли отладки вызов [UIApplication terminateWithSuccess] приведет к тому, что приложение завершится "правильно", но все равно оставит зомби... интересно, если у вас установлена точка останова, приложение не завершит работу:
(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
[(UIApplication *)[UIApplication sharedApplication] terminateWithSuccess]
error: Execution was interrupted, reason: breakpoint 2.1.
The process has been returned to the state before execution.
(lldb) breakpoint disable 2.1
1 breakpoints disabled.
(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
[(UIApplication *)[UIApplication sharedApplication] terminateWithSuccess]
2013-03-25 01:28:00.186 iPhone Testbed[9481:c07] -[AppDelegate applicationWillTerminate:]
(lldb)
Таким образом, приложение проходит какой-то процесс выключения, и шоу прекращает показы в консоли, но у нас все еще есть зомби, так что это все еще не чистое завершение работы.
Я думаю, что все это связано с тем, что приложение работает в фоновом режиме во время работы iOS. При непосредственном манипулировании процессами (с помощью кнопки "Стоп", команды "kill", "Отладка консоли" и т. Д. И т. Д.) Во время выполнения iOS не разрешается производить надлежащее выключение и очистку - фактически, трамплин по-прежнему считает, что приложение работает в фоновом режиме, даже когда процесс больше не существует. Так получилось, что наши среды выполнения iOS и OS X - одно и то же - отсюда и запуск зомби.
Поэтому я думаю, что решением всего этого является определение процедуры чистого выключения на уровне iOS и, по крайней мере, возможность выполнить ее через консоль отладки. Собираюсь больше взглянуть на флаг UIApplicationExitsOnSuspend, посмотреть, смогу ли я установить необходимые биты во время выполнения (в отличие от plist), чтобы корректно завершить работу приложения после отладочной отсоединения...