readline hangs on manual pipe()











up vote
3
down vote

favorite












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:




  • calling $w->autoflush(1)

  • explicit close on handles

  • explicit exit

  • POSIX::dup2 $w onto STDOUT

  • checking strace -ff to see whether I missed a crucial syscall


What's the problem?










share|improve this question






















  • I believe Shawn's answer is correct; reading continues to block because the pipe is still open for writing (by the parent). But you do say you tried explicitly closing handles; did you try closing the write handle in the parent (before the getline)?
    – ysth
    yesterday

















up vote
3
down vote

favorite












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:




  • calling $w->autoflush(1)

  • explicit close on handles

  • explicit exit

  • POSIX::dup2 $w onto STDOUT

  • checking strace -ff to see whether I missed a crucial syscall


What's the problem?










share|improve this question






















  • I believe Shawn's answer is correct; reading continues to block because the pipe is still open for writing (by the parent). But you do say you tried explicitly closing handles; did you try closing the write handle in the parent (before the getline)?
    – ysth
    yesterday















up vote
3
down vote

favorite









up vote
3
down vote

favorite











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:




  • calling $w->autoflush(1)

  • explicit close on handles

  • explicit exit

  • POSIX::dup2 $w onto STDOUT

  • checking strace -ff to see whether I missed a crucial syscall


What's the problem?










share|improve this question













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:




  • calling $w->autoflush(1)

  • explicit close on handles

  • explicit exit

  • POSIX::dup2 $w onto STDOUT

  • checking strace -ff to see whether I missed a crucial syscall


What's the problem?







perl posix






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









daxim

35.8k449112




35.8k449112












  • I believe Shawn's answer is correct; reading continues to block because the pipe is still open for writing (by the parent). But you do say you tried explicitly closing handles; did you try closing the write handle in the parent (before the getline)?
    – ysth
    yesterday




















  • I believe Shawn's answer is correct; reading continues to block because the pipe is still open for writing (by the parent). But you do say you tried explicitly closing handles; did you try closing the write handle in the parent (before the getline)?
    – ysth
    yesterday


















I believe Shawn's answer is correct; reading continues to block because the pipe is still open for writing (by the parent). But you do say you tried explicitly closing handles; did you try closing the write handle in the parent (before the getline)?
– ysth
yesterday






I believe Shawn's answer is correct; reading continues to block because the pipe is still open for writing (by the parent). But you do say you tried explicitly closing handles; did you try closing the write handle in the parent (before the getline)?
– ysth
yesterday














1 Answer
1






active

oldest

votes

















up vote
3
down vote



accepted










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).






share|improve this answer





















  • Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
    – ikegami
    5 hours ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53372637%2freadline-hangs-on-manual-pipe%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
3
down vote



accepted










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).






share|improve this answer





















  • Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
    – ikegami
    5 hours ago















up vote
3
down vote



accepted










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).






share|improve this answer





















  • Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
    – ikegami
    5 hours ago













up vote
3
down vote



accepted







up vote
3
down vote



accepted






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).






share|improve this answer












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).







share|improve this answer












share|improve this answer



share|improve this answer










answered yesterday









Shawn

3,0441513




3,0441513












  • Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
    – ikegami
    5 hours ago


















  • Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
    – ikegami
    5 hours ago
















Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
– ikegami
5 hours ago




Key piece of missing info: The pipe will only return EOF once there are no open handles to the write end of the pipe.
– ikegami
5 hours ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53372637%2freadline-hangs-on-manual-pipe%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

ts Property 'filter' does not exist on type '{}'

mat-slide-toggle shouldn't change it's state when I click cancel in confirmation window