Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Windows and pipes that don't close

by salva (Abbot)
on Dec 10, 2014 at 16:10 UTC ( #1109928=perlquestion: print w/replies, xml ) Need Help??
salva has asked for the wisdom of the Perl Monks concerning the following question:

I am working on a new backend for my Net::SSH::Any module which uses an external SSH client (ssh or plink) to connect to the remote host. Net::SSH::Any is quite flexible in terms of setting redirections for the remote program streams or capturing the data, so I have developed a layer that is able to handle that and that works on Linux/Unix... and almost on Windows!

The issue I am facing on Windows is that when I run the slave process with its STDIN stream attached to a pipe and, after writing something, I close the perl side, the slave doesn't get the EOF.

The following program shows the issue:

open my $oldin, '<&', \*STDIN or die $!; pipe my($r), my ($w) or die $!; open STDIN, '<&', $r or die $!; my $pid = system 1, 'perl -ne print'; print "pid: $pid\n"; close STDIN or die $!; open STDIN, '<&', $oldin; close $r or die $!; print {$w} "hello world! ($_)\n" for 0..9; close $w or die $!; print "waiting for slave process\n"; waitpid $pid, 0 or die $!

If you run it you will see that the program stalls waiting for the slave to finish.

I can also reproduce the issue with IPC::Open2 open2:

use IPC::Open2 qw(open2); my $pid = open2 ">&STDOUT", my($w), 'perl -ne print' or die $!; print "pid: $pid\n"; print {$w} "hello world! ($_)\n" for 0..9; close $w or die $!; print "waiting for slave process\n"; waitpid $pid, 0 or die $!

On the other hand, when a regular file is used, everything works as expected:

open my $oldin, '<&', \*STDIN or die $!; open STDIN, '<&', \*DATA or die $!; my $pid = system 1, 'perl -ne print'; print "pid: $pid\n"; close STDIN or die $!; open STDIN, '<&', $oldin; print "waiting for slave process\n"; waitpid $pid, 0 or die $! __DATA__ hello world! (from DATA)
And creating the pipe using open with mode |- also works (but I don't want to do it that way because I may also need to redirect STDOUT and STDERR):
my $pid = open my $w, '|-', 'perl -ne print' or die $!; print "pid: $pid\n"; print {$w} "hello world! ($_)\n" for 0..9; close $w or die $!; print "waiting for slave process\n"; waitpid $pid, 0 or die $!
Does anybody have a clue what's going on?

All that occurs to me is that the slave may be inheriting also the write side of the pipe.

Replies are listed 'Best First'.
Re: Windows and pipes that don't close (close-on-exec)
by tye (Sage) on Dec 10, 2014 at 16:27 UTC

    That means that you aren't managing to get all of the dup()s of the file handle closed.

    I wouldn't be surprised if $^F has some problems in Win32 (though perlport does not mention it).

    See SetHandleInformation and HANDLE_FLAG_INHERIT in Win32API::File.

    - tye        

      Unsetting HANDLE_FLAG_INHERIT works!
      open my $oldin, '<&', \*STDIN or die $!; pipe my($r), my ($w) or die $!; open STDIN, '<&', $r or die $!; my $wh = FdGetOsFHandle(fileno $w); SetHandleInformation($wh, HANDLE_FLAG_INHERIT, 0); my $pid = system 1, 'perl -ne print'; print "pid: $pid\n"; close STDIN or die $!; open STDIN, '<&', $oldin; close $r or die $!; print {$w} "hello world! ($_)\n" for 0..9; close $w or die $!; print "waiting for slave process\n"; waitpid $pid, 0 or die $!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1109928]
Approved by marto
Front-paged by marto
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2018-01-19 04:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How did you see in the new year?










    Results (215 votes). Check out past polls.

    Notices?