2010-09-22 6 views
2

У меня есть программа, которая зовет другую программу и обработку вывода ребенка, то есть:Как сделать неблокирующее чтение из канала в Perl?

my $pid = open($handle, "$commandPath $options |"); 

Теперь я попробовал несколько различных способов, чтобы читать от ручки без блокировки с небольшим или без успеха.

Я нашел похожие вопросы:

Но они страдают от проблем:

  • ioctl стабильно падает Perl
  • sysread блокировки по 0 байтам (обычное явление)

Я не уверен, как решить эту проблему.

+0

Это Windows? – mob

+0

См. [Этот ответ] (http://stackoverflow.com/questions/1530592/why-does-my-perl-sysread-block-when-reading-from-a-socket/1532251#1532251) - используйте 'select() ', чтобы определить, есть ли доступные данные для чтения. – Ether

+0

@ Едкий выбор не работает с файловыми дескрипторами на окнах – tzenes

ответ

4

Трубы не такие функциональные в Windows, как в системах Unix-y. Вы не можете использовать 4-аргумент select на них, а емкость по умолчанию минимальна.

Лучше попробуйте обходной путь к сокету или файлу.

$pid = fork(); 
if (defined($pid) && $pid == 0) { 
    exit system("$commandPath $options > $someTemporaryFile"); 
} 
open($handle, "<$someTemporaryFile"); 

Теперь у вас есть еще пару банок червей, чтобы иметь дело с - бег waitpid периодически проверять, когда фоновый процесс прекратил создание вывода, вызывая seek $handle,0,1 очистить состояние ВФ после того, как вы читаете из $handle, уборка временный файл, но он работает.

Я написал модуль Forks::Super для решения таких проблем (и многих других). Для этой проблемы вы использовали бы это как

use Forks::Super; 
my $pid = fork { cmd => "$commandPath $options", child_fh => "out" }; 
my $job = Forks::Super::Job::get($pid); 
while (!$job->is_complete) { 
    @someInputToProcess = $job->read_stdout(); 
    ... process input ... 
    ... optional sleep here so you don't consume CPU waiting for input ... 
} 
waitpid $pid, 0; 
@theLastInputToProcess = $job->read_stdout(); 
+0

@mobrule Мое понимание - я не могу использовать select на дескрипторе файла, так что это просто воссоздает ту же проблему, что у меня в настоящее время. – tzenes

+0

Вам не нужно использовать select на дескрипторе файла. Чтение устаревшего дескриптора файла вернет 'undef' без блокировки, а затем вы можете вызвать' seek HANDLE, 0,1', чтобы очистить условие eof и прочитать его снова. – mob

+0

@mob, тогда мне нужно будет искать, насколько далеко я уже прочитал? Или это справляется с этим? – tzenes

Смежные вопросы