As a general policy, I avoid backticks and instead rely on Capture::Tiny and system calls.
my ( $stdout, $stderr, @results ) = capture { system($command) };
However, I just ran into an exception internal to Capture::Tiny when used under HTML::Mason that I had not seen before
Error from open(GLOB(0x555ef4527090), >&-1): Invalid argument at /usr/share/perl5/vendor_perl/Capture/Tiny.pm line 107.
Capture::Tiny::_open(GLOB(0x555ef4527090), ">\\x{26}-1") called at /usr/share/perl5/vendor_perl/Capture/Tiny.pm line 194
Capture::Tiny::_open_std(HASH(0x555ec25b12b8)) called at /usr/share/perl5/vendor_perl/Capture/Tiny.pm line 391
Capture::Tiny::_capture_tee(1, 1, 0, 0, CODE(0x555f05d5ce70)) called at InternalModule.pm line 41
...
InternalModule.pm called at /.../apache/htdocs/autohandler line 84
HTML::Mason::Commands::__ANON__() called at /usr/share/perl5/vendor_perl/HTML/Mason/Component.pm line 135
This is a legacy system, so the module versions are a little old.
Doing some internals diving into Capture::Tiny shows this method is throwing the exception
sub _open {
open $_[0], $_[1] or Carp::confess "Error from open(" . join(q{, }, @_) . "): $!"; # Line 107
# _debug( "# open " . join( ", " , map { defined $_ ? _name($_) : 'undef' } @_ ) . " as " . fileno( $_[0] ) . "\n" );
}
And specifically, it's the opening of STDOUT that is calling _open and leading to the exception:
# In some cases we open all (prior to forking) and in others we only open
# the output handles (setting up redirection)
sub _open_std {
my ($handles) = @_;
_open \*STDIN, "<&" . fileno $handles->{stdin} if defined $handles->{stdin};
_open \*STDOUT, ">&" . fileno $handles->{stdout} if defined $handles->{stdout}; # Line 194
_open \*STDERR, ">&" . fileno $handles->{stderr} if defined $handles->{stderr};
}
I've attempted localizing *STDOUT, although it appears that Capture::Tiny already does this.
For now I'm concluding that I should just go with a solution like this
system("program args 1>program.stdout 2>program.stderr");
Is there something else I'm missing with regard to Capture::Tiny to make it work while under Mason?