readline висит на ручной трубе () - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь развеять вариант волшебной вилки open:

# magic-fork.pl
if (open my $fh, '-|') { # fork self, make new fd for reading, attach child STDOUT to it
    STDOUT->say('parent getpid: ', $$);
    STDOUT->say('parent STDOUT->fileno: ', STDOUT->fileno);
    STDOUT->say('parent $fh->fileno: ', $fh->fileno);
    while (my $line = $fh->getline) {
        STDOUT->print('parent readline from child: ', $line);
    }
} else {
    STDOUT->say('child getpid: ', $$);
    STDOUT->say('child STDOUT->fileno: ', STDOUT->fileno);
}

Он запускается и заканчивается.

# plain-fork.pl
pipe my $r, my $w;
if (fork) {
    STDOUT->say('parent getpid: ', $$);
    STDOUT->say('parent STDOUT->fileno: ', STDOUT->fileno);
    STDOUT->say('parent $r->fileno: ', $r->fileno);
    STDOUT->say('parent $w->fileno: ', $w->fileno);
    while (my $line = $r->getline) {
        STDOUT->print('parent readline from child: ', $line);
    }
} else {
    $w->say('child getpid: ', $$);
    $w->say('child $r->fileno: ', $r->fileno);
    $w->say('child $w->fileno: ', $w->fileno);
    $w->say('child STDOUT->fileno: ', STDOUT->fileno);
}

Эта программа неожиданно зависает в цикле.

Я пытался безрезультатно:

  • вызов $ w-> autoflush (1)
  • явное закрытие на дескрипторах
  • явное завершение
  • POSIX :: dup2 $ w на STDOUT
  • проверка strace -ff, чтобы увидеть, пропустил ли я критический системный вызов

В чем проблема?

1 Ответ

0 голосов
/ 19 ноября 2018

Вы pipe до fork ing (как обычно для такого рода IPC), поэтому оба процесса имеют открытые копии дескрипторов файлов для чтения и записи, поэтому цикл чтения в родительском элементе просто блокирует ожидание большего количества ввод, который никогда не приходит с еще открытого конца записи.

Дочернему процессу нужно close $r;, родительскому процессу - close $w; в начале их соответствующих блоков (или после того, как вы распечатаете файловые дескрипторы для этих дескрипторов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...