Процесс зависает и ТРУБА заблокирована
Кажется, у меня тупик. У меня есть perl-скрипты разветвления и вызова других perl-скриптов. И процесс где-то зависает.
Я запускаю программу на: Darwin Kernel Версия 12.3.0: Вс 6 января 22:37:10 PST 2013; root: xnu-2050.22.13 ~ 1 / RELEASE_X86_64 x86_64
"lsof" имеет 4 записи, относящиеся к одной и той же ТРУБЕ:
perl5.12 1414 root 1 ТРУБА 0x48937dc1254fe937 16384 ->0x48937dc1254fe727
perl5.12 1768 root 1 ТРУБА 0x48937dc1254fe937 16384 ->0x48937dc1254fe727
perl5.12 1759 root 1 ТРУБА 0x48937dc1254fe937 16384 ->0x48937dc1254fe727
perl5.12 1760 root 1 ТРУБА 0x48937dc1254fe937 16384 ->0x48937dc1254fe727
Я подозреваю, что это является причиной зависания. Есть ли у нас какие-либо команды, которые могли бы сказать мне, какой процесс чтения / записи в эту ТРУБУ? Или любая дополнительная информация будет оценена. Заранее спасибо!
2 ответа
Есть две вероятные возможности, о которых я могу думать:
Есть тупик из-за буферизации вывода. Попробуйте включить автозапуск на всех выходных каналах. Это вероятно, если два процесса обмениваются данными в двух направлениях с использованием каналов: каждый из них что-то записывает и ожидает чтения ответа, но поскольку выходные данные буферизуются, ответ никогда не отправляется в канал.
Процесс ожидает EOF на конвейере, но он никогда не приходит. Если канал создан в родительском процессе, а затем унаследован дочерним процессом, необходимо убедиться, что все процессы закрывают конец записи канала, чтобы читатель мог прочитать EOF.
Как объяснил Бармар, дочерние процессы могут застрять при заполнении буфера вывода. В этом случае вы обнаружите, что дочерний процесс застрял в write()
Вызов функции.
Вам придется использовать Perl IO::Select
Модуль в родительском процессе для постоянного чтения выходного буфера из дочернего процесса и, следовательно, его очистки, если выход из дочернего процесса больше, чем буфер.
Официальная документация Perl по адресу http://perldoc.perl.org/functions/sysread.html объясняет:
sysread FILEHANDLE, SCALAR, LENGTH
Пытается прочитать ДЛИННЫЕ байты данных в переменную SCALAR из указанного FILEHANDLE, используя read(2). Он обходит буферизованный ввод-вывод, поэтому смешивание его с другими типами операций чтения, печати, записи, поиска, передачи или eof может вызвать путаницу, поскольку слои perlio или stdio обычно буферизуют данные.
Далее, чтобы увидеть Системную активность, я обычно использую strace
Команда, которая хорошо показывает, как каждый процесс читает и записывает данные.