perl5
perl5 copied to clipboard
[doc] IPC::Open3 - send STDOUT and STDERR to already open handle
Where https://perldoc.perl.org/IPC::Open3
Description The documentation state that we can redirect STDIN/STDOUT/STDERR to an already open handle.
# read from parent STDIN
# send STDOUT and STDERR to already open handle
open my $outfile, '>>', 'output.txt' or die "open failed: $!";
my $pid = open3('<&STDIN', $outfile, undef,
'some', 'cmd', 'and', 'args');
But, at least on linux, it doesn't work. This sample code generates an empty file:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3;
open my $outfile, '>', 'out.txt' or die "open failed: $!";
my $pid = open3('<&STDIN', $outfile, '>&STDERR', 'id');
waitpid($pid, 0);
close($outfile);
We can see with strace that perl closes the file descriptor beforing cloning:
...
openat(AT_FDCWD, "out.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
ioctl(3, TCGETS, 0x7ffe44688080) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
close(3) = 0
pipe([3, 4]) = 0
...
It happens here: https://github.com/Perl/perl5/blob/blead/ext/IPC-Open3/lib/IPC/Open3.pm#L242
The code works as expected if we provides manually the file descriptor via >&3
Where https://perldoc.perl.org/IPC::Open3
Description The documentation state that we can redirect STDIN/STDOUT/STDERR to an already open handle.
# read from parent STDIN # send STDOUT and STDERR to already open handle open my $outfile, '>>', 'output.txt' or die "open failed: $!"; my $pid = open3('<&STDIN', $outfile, undef, 'some', 'cmd', 'and', 'args');But, at least on linux, it doesn't work. This sample code generates an empty file:
#!/usr/bin/perl use strict; use warnings; use IPC::Open3; open my $outfile, '>', 'out.txt' or die "open failed: $!";
In the code sample from the IPC::Open3 docs you quoted above, the second argument to open is >. In your own example above, the second argument to open is >>. Is that difference significant?
my $pid = open3('<&STDIN', $outfile, '>&STDERR', 'id'); waitpid($pid, 0);
close($outfile);
We can see with strace that perl closes the file descriptor beforing cloning:... openat(AT_FDCWD, "out.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 ioctl(3, TCGETS, 0x7ffe44688080) = -1 ENOTTY (Inappropriate ioctl for device) lseek(3, 0, SEEK_CUR) = 0 fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 close(3) = 0 pipe([3, 4]) = 0 ...
It happens here: https://github.com/Perl/perl5/blob/blead/ext/IPC-Open3/lib/IPC/Open3.pm#L242 The code works as expected if we provides manually the file descriptor via `>&3`
Can you provide a code sample for what you mean by manually providing the file descriptor via >&3?
I did the test with both > and >> it's the same.
3 is the first free file descriptor, a proper code sample would be:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3;
open my $outfile, '>', 'out.txt' or die "open failed: $!";
my $pid = open3('<&STDIN', '>&' . fileno($outfile), '>&STDERR', 'id');
waitpid($pid, 0);
close($outfile);
I did the test with both
>and>>it's the same.
3is the first free file descriptor, a proper code sample would be:#!/usr/bin/perl use strict; use warnings; use IPC::Open3; open my $outfile, '>', 'out.txt' or die "open failed: $!"; my $pid = open3('<&STDIN', '>&' . fileno($outfile), '>&STDERR', 'id'); waitpid($pid, 0); close($outfile);
Could you please file a pull request with that code?
The documentation state that we can redirect STDIN/STDOUT/STDERR to an already open handle.
And you can.
open( local *CHILD_OUT, ">", "outfile.txt" ) or die $!;
my $pid = open3("<&STDIN", ">&CHILD_OUT", undef, ... );
I don't think the approach used in the documentation has ever worked.
The documentation state that we can redirect STDIN/STDOUT/STDERR to an already open handle.
And you can.
open( local *CHILD_OUT, ">", "outfile.txt" ) or die $!; my $pid = open3("<&STDIN", ">&CHILD_OUT", undef, ... );
Or if you start with an arbitrary handle,
open( local *CHILD_OUT, ">&=", $fh ) or die $!;
my $pid = open3("<&STDIN", ">&CHILD_OUT", undef, ... );
I avoid IPC::Open3. I recommend IPC::Run.
I don't think the approach used in the documentation has ever worked.
I've just wasted far too much time due to attempting to follow this example in the IPC::Open3 docs. Couldn't it at least be removed if it doesn't work and has never worked?