daxim
daxim

Reputation: 39158

readline hangs on manual pipe()

I'm trying to dispel the magic fork variant of 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);
}

It runs and finishes.

# 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);
}

This program unexpectedly hangs in the loop.

I tried to no avail:

What's the problem?

Upvotes: 3

Views: 185

Answers (1)

Shawn
Shawn

Reputation: 52579

You pipe before forking (Like usual for this sort of IPC), so both processes have open copies of both the read and write file descriptors, so the read loop in the parent will just block waiting for more input which never comes from the still-open write end.

The child process needs to close $r;, the parent process needs to close $w; at the start of their respective blocks (Or after you print out the file descriptors for those handles).

Upvotes: 3

Related Questions