Проблемы с NSTask в OS X 10.6 Snow Leopard - PullRequest
2 голосов
/ 30 августа 2009

Кто-нибудь еще видел или слышал о каких-либо проблемах с NSTask в 10.6?

Вчера этот код работал нормально, а сегодня не работает.

NSTask *task = [converter task];
[task waitUntilExit];
NSLog(@"Task did complete");

Задача выполняет то, что должна (я проверила вывод и все нормально), но программа будет ждать бесконечно долго waitUntilExit метод. У меня есть несколько модульных тестов, которые используют похожий код, все они прошли ранее, но со вчерашнего дня они больше не работают.

Ответы [ 5 ]

2 голосов
/ 04 сентября 2010

Вам необходимо добавить следующую магическую строку:

[task setStandardInput:[NSPipe pipe]];
1 голос
/ 30 августа 2009

(1) Обрабатываете ли вы выход из задания каким-либо образом? Если это так, буферизация вывода может блокироваться, если вы не читаете и не обрабатываете данные по пути.

(2) Ваша задача ожидает EOL на стандартном вводе перед завершением? Если это так, вы захотите захватить stdin и явно закрыть его.

Как сказал Питер, проверьте ps, чтобы увидеть, выполняется ли еще ваша задача. Если это так, используйте sample, чтобы выяснить, что это такое.

1 голос
/ 31 августа 2009

Возможно, я заметил проблему с некоторым кодом на 10.6, который звучит подозрительно, как ваша проблема.

Мне нужно было получить некоторую информацию о сети (в основном касающуюся BGP и AS) полностью асинхронным способом. Идеальным решением для меня является отправка специальных запросов записи DNS TXT на общедоступный DNS-сервер, но Cocoa / Core Foundation не предоставляет API для выполнения такого рода нечетких DNS-запросов. Другим способом было использовать shell% whois -h IP 'SPECIAL REQUEST' и просто анализировать соответствующую информацию из вывода. Это было то, что я мог бы запустить и запустить в течение нескольких часов и вернуться позже и найти реальное решение. Очень хакерский, но намного быстрее, чем 1) поиск подходящей асинхронной библиотеки DNS и 2) ускорение работы с ее API и, возможно, написание оболочки для нее.

Итак, я создал класс, который разветвляет фоновый поток, а затем NSTask, чтобы запустить запрос whois. Фоновый поток находится в цикле NSRunLoop для обработки результатов, но проверяет каждую ~ 1/10 секунды, чтобы узнать, умер ли NSTask по какой-либо причине, или если [NSThread isCanceled], и т. Д. И т. Д. Он также регистрируется для NSApplicationWillTerminateNotification уведомлений, чтобы он мог выполнить надлежащую очистку, если приложение закрывается.

Ну, по состоянию на 10.6 ... я больше не мог бросать «быстро». На 10.5 все гладко, и приложение закрывается мгновенно, по крайней мере, перцептивно. При выходе из версии 10.6 приложение «зависает». Отладка показала, что все зависало, пытаясь убрать затяжные whois NSTask s. Поскольку никакая информация, которую я получаю таким образом, не имеет решающего значения для функциональности приложений (это дополнительная, приятно знать, какая-то информация), я просто отчасти заболел и перестал пытаться получить эту информацию в качестве решения для ограничения пробела.

Быстрые попытки отладки проблемы показали, что основное приложение блокировало попытки получить экземпляры NSLock. Интересно то, что если я просто оставлю это в покое, приложение в конце концов выйдет нормально - где-то от 10-20 секунд до минут ... что-то изменилось между 10,5 и 10,6, что приводит к тому, что код в скобках внутри блока [NSLock lock] ... [NSLock unlock] "занимает много времени". время'. Мне еще предстоит отследить, где это происходит, хотя (пока не приоритет) .... но одна из этих вещей - завершение фона NSTask, если он все еще работает, и «ожидание его завершения», прежде чем он сможет безопасно избавиться от таких вещей, как NSPipe.

DUP : Это может быть дурацкий ответ ... мой первый, похоже, исчез в одном из них?

0 голосов
/ 16 сентября 2010

Не уверен, поможет ли это, но вы можете попробовать выполнить ожидание в отдельном потоке:

[NSThread detachNewThreadSelector: @selector(foo) toTarget: self withObject: task];

...

- (void) foo: (NSTask *) task {
  [task launch];
  [task waitUntilExit];
  ...

У меня была проблема, когда я не получил NSNotification, когда задача была выполнена, и это исправило ее. Видимо, есть некоторые ошибки в реализации NSTask под 10.6 ...

0 голосов
/ 30 августа 2009

Проверьте ps, top или Activity Monitor. Убедитесь, что ваш процесс завершен.

...