Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Windows and pipes that don't close

by salva (Canon)
on Dec 10, 2014 at 16:10 UTC ( [id://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
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1109928]
Approved by marto
Front-paged by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (2)
As of 2024-04-16 23:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found