App-Dex
view release on metacpan or search on metacpan
scripts/dex view on Meta::CPAN
defined $r
&& ( $r == -1 || ( is_win32 && $r == 0xFF00 ) )
&& !$options->{return_if_system_error}
) {
croak( $errno );
}
1;
};
my $x = $@;
my @errs;
if ( defined $saved_fd0 ) {
dup2( $saved_fd0, 0 );
POSIX::close( $saved_fd0 );
}
# open STDIN, "<&STDIN_SAVE"# or push @errs, "run3(): $! restoring STDIN"
# if defined $in_fh;
open STDOUT, ">&STDOUT_SAVE" or push @errs, "run3(): $! restoring STDOUT"
if defined $out_fh;
open STDERR, ">&STDERR_SAVE" or push @errs, "run3(): $! restoring STDERR"
if defined $err_fh;
croak join ", ", @errs if @errs;
die $x unless $ok;
_read_child_output_fh "stdout", $out_type, $stdout, $out_fh, $options
if defined $out_fh && $out_type && $out_type ne "FH";
_read_child_output_fh "stderr", $err_type, $stderr, $err_fh, $options
if defined $err_fh && $err_type && $err_type ne "FH" && !$tie_err_to_out;
$profiler->run_exit(
$cmd,
$run_call_time,
$sys_call_time,
$sys_exit_time,
scalar gettimeofday()
) if profiling;
$! = $errno; # restore $! from system()
return 1;
}
1;
__END__
=head2 C<< run3($cmd, $stdin, $stdout, $stderr, \%options) >>
All parameters after C<$cmd> are optional.
The parameters C<$stdin>, C<$stdout> and C<$stderr> indicate how the child's
corresponding filehandle (C<STDIN>, C<STDOUT> and C<STDERR>, resp.) will be
redirected. Because the redirects come last, this allows C<STDOUT> and
C<STDERR> to default to the parent's by just not specifying them -- a common
use case.
C<run3> throws an exception if the wrapped C<system> call returned -1 or
anything went wrong with C<run3>'s processing of filehandles. Otherwise it
returns true. It leaves C<$?> intact for inspection of exit and wait status.
Note that a true return value from C<run3> doesn't mean that the command had a
successful exit code. Hence you should always check C<$?>.
See L</%options> for an option to handle the case of C<system> returning -1
yourself.
=head3 C<$cmd>
Usually C<$cmd> will be an ARRAY reference and the child is invoked via
system @$cmd;
But C<$cmd> may also be a string in which case the child is invoked via
system $cmd;
(cf. L<perlfunc/system> for the difference and the pitfalls of using
the latter form).
=head3 C<$stdin>, C<$stdout>, C<$stderr>
The parameters C<$stdin>, C<$stdout> and C<$stderr> can take one of the
following forms:
=over 4
=item C<undef> (or not specified at all)
The child inherits the corresponding filehandle from the parent.
run3 \@cmd, $stdin; # child writes to same STDOUT and STDERR as parent
run3 \@cmd, undef, $stdout, $stderr; # child reads from same STDIN as parent
=item C<\undef>
The child's filehandle is redirected from or to the local equivalent of
C</dev/null> (as returned by C<< File::Spec->devnull() >>).
run3 \@cmd, \undef, $stdout, $stderr; # child reads from /dev/null
=item a simple scalar
The parameter is taken to be the name of a file to read from
or write to. In the latter case, the file will be opened via
open FH, ">", ...
i.e. it is created if it doesn't exist and truncated otherwise.
Note that the file is opened by the parent which will L<croak|Carp/croak>
in case of failure.
run3 \@cmd, \undef, "out.txt"; # child writes to file "out.txt"
=item a filehandle (either a reference to a GLOB or an C<IO::Handle>)
The filehandle is inherited by the child.
scripts/dex view on Meta::CPAN
For C<$stdout> or C<$stderr>, the child's corresponding file descriptor
is read line by line (as determined by the current setting of C<$/>)
and C<&$stdout> or C<&$stderr>, resp., is called with the contents of the line.
Note that there's no end-of-file indication.
my $i = 0;
sub producer {
return $i < 10 ? "line".$i++."\n" : undef;
}
run3 \@cmd, \&producer; # child reads 10 lines
Note that this form of redirecting the child's I/O doesn't imply
any form of concurrency between parent and child - run3()'s method of
operation is the same no matter which form of redirection you specify.
=back
If the same value is passed for C<$stdout> and C<$stderr>, then the child
will write both C<STDOUT> and C<STDERR> to the same filehandle.
In general, this means that
run3 \@cmd, \undef, "foo.txt", "foo.txt";
run3 \@cmd, \undef, \$both, \$both;
will DWIM and pass a single file handle to the child for both C<STDOUT> and
C<STDERR>, collecting all into file "foo.txt" or C<$both>.
=head3 C<\%options>
The last parameter, C<\%options>, must be a hash reference if present.
Currently the following keys are supported:
=over 4
=item C<binmode_stdin>, C<binmode_stdout>, C<binmode_stderr>
The value must a "layer" as described in L<perlfunc/binmode>. If specified the
corresponding parameter C<$stdin>, C<$stdout> or C<$stderr>, resp., operates
with the given layer.
For backward compatibility, a true value that doesn't start with ":"
(e.g. a number) is interpreted as ":raw". If the value is false
or not specified, the default is ":crlf" on Windows and ":raw" otherwise.
Don't expect that values other than the built-in layers ":raw", ":crlf",
and (on newer Perls) ":bytes", ":utf8", ":encoding(...)" will work.
=item C<append_stdout>, C<append_stderr>
If their value is true then the corresponding parameter C<$stdout> or
C<$stderr>, resp., will append the child's output to the existing "contents" of
the redirector. This only makes sense if the redirector is a simple scalar (the
corresponding file is opened in append mode), a SCALAR reference (the output is
appended to the previous contents of the string) or an ARRAY reference (the
output is C<push>ed onto the previous contents of the array).
=item C<return_if_system_error>
If this is true C<run3> does B<not> throw an exception if C<system> returns -1
(cf. L<perlfunc/system> for possible failure scenarios.), but returns true
instead. In this case C<$?> has the value -1 and C<$!> contains the errno of
the failing C<system> call.
=back
=head1 HOW IT WORKS
=over 4
=item (1)
For each redirector C<$stdin>, C<$stdout>, and C<$stderr>, C<run3()> furnishes
a filehandle:
=over 4
=item *
if the redirector already specifies a filehandle it just uses that
=item *
if the redirector specifies a filename, C<run3()> opens the file
in the appropriate mode
=item *
in all other cases, C<run3()> opens a temporary file (using
L<tempfile|Temp/tempfile>)
=back
=item (2)
If C<run3()> opened a temporary file for C<$stdin> in step (1),
it writes the data using the specified method (either
from a string, an array or returned by a function) to the temporary file and rewinds it.
=item (3)
C<run3()> saves the parent's C<STDIN>, C<STDOUT> and C<STDERR> by duplicating
them to new filehandles. It duplicates the filehandles from step (1)
to C<STDIN>, C<STDOUT> and C<STDERR>, resp.
=item (4)
C<run3()> runs the child by invoking L<system|perlfunc/system> with C<$cmd> as
specified above.
=item (5)
C<run3()> restores the parent's C<STDIN>, C<STDOUT> and C<STDERR> saved in step (3).
=item (6)
If C<run3()> opened a temporary file for C<$stdout> or C<$stderr> in step (1),
it rewinds it and reads back its contents using the specified method (either to
a string, an array or by calling a function).
=item (7)
C<run3()> closes all filehandles that it opened explicitly in step (1).
=back
Note that when using temporary files, C<run3()> tries to amortize the overhead
by reusing them (i.e. it keeps them open and rewinds and truncates them
before the next operation).
=head1 LIMITATIONS
Often uses intermediate files (determined by File::Temp, and thus by the
File::Spec defaults and the TMPDIR env. variable) for speed, portability and
simplicity.
Use extreme caution when using C<run3> in a threaded environment if concurrent
calls of C<run3> are possible. Most likely, I/O from different invocations will
get mixed up. The reason is that in most thread implementations all threads in
a process share the same STDIN/STDOUT/STDERR. Known failures are Perl ithreads
on Linux and Win32. Note that C<fork> on Win32 is emulated via Win32 threads
and hence I/O mix up is possible between forked children here (C<run3> is "fork
safe" on Unix, though).
=head1 DEBUGGING
To enable debugging use the IPCRUN3DEBUG environment variable to
a non-zero integer value:
$ IPCRUN3DEBUG=1 myapp
=head1 PROFILING
To enable profiling, set IPCRUN3PROFILE to a number to enable emitting profile
information to STDERR (1 to get timestamps, 2 to get a summary report at the
END of the program, 3 to get mini reports after each run) or to a filename to
emit raw data to a file for later analysis.
=head1 COMPARISON
Here's how it stacks up to existing APIs:
=head2 compared to C<system()>, C<qx''>, C<open "...|">, C<open "|...">
=over
=item *
better: redirects more than one file descriptor
=item *
better: returns TRUE on success, FALSE on failure
=item *
better: throws an error if problems occur in the parent process (or the
pre-exec child)
=item *
better: allows a very perlish interface to Perl data structures and subroutines
=item *
better: allows 1 word invocations to avoid the shell easily:
run3 ["foo"]; # does not invoke shell
=item *
worse: does not return the exit code, leaves it in $?
=back
=head2 compared to C<open2()>, C<open3()>
=over
=item *
better: no lengthy, error prone polling/select loop needed
=item *
better: hides OS dependencies
=item *
better: allows SCALAR, ARRAY, and CODE references to source and sink I/O
=item *
better: I/O parameter order is like C<open3()> (not like C<open2()>).
=item *
worse: does not allow interaction with the subprocess
=back
=head2 compared to L<IPC::Run::run()|IPC::Run/run>
=over
=item *
better: smaller, lower overhead, simpler, more portable
=item *
better: no select() loop portability issues
=item *
better: does not fall prey to Perl closure leaks
scripts/dex view on Meta::CPAN
Like in modules like L<YAML>, the Constructor will use references for mappings and
sequences, but obviously not for scalars.
L<YAML::XS> uses real aliases, which allows also aliasing scalars. I might add
an option for that since aliasing is now available in pure perl.
=item Boolean Handling
You can choose between C<'perl'> (1/'', currently default), C<'JSON::PP'> and
C<'boolean'>.pm for handling boolean types. That allows you to dump the data
structure with one of the JSON modules without losing information about
booleans.
=item Numbers
Numbers are created as real numbers instead of strings, so that they are
dumped correctly by modules like L<JSON::PP> or L<JSON::XS>, for example.
=item Complex Keys
Mapping Keys in YAML can be more than just scalars. Of course, you can't load
that into a native perl structure. The Constructor will stringify those keys
with L<Data::Dumper> instead of just returning something like
C<HASH(0x55dc1b5d0178)>.
Example:
use YAML::PP;
use JSON::PP;
my $ypp = YAML::PP->new;
my $coder = JSON::PP->new->ascii->pretty->allow_nonref->canonical;
my $yaml = <<'EOM';
complex:
?
?
a: 1
c: 2
: 23
: 42
EOM
my $data = $yppl->load_string($yaml);
say $coder->encode($data);
__END__
{
"complex" : {
"{'{a => 1,c => 2}' => 23}" : 42
}
}
=back
TODO:
=over 4
=item Parse Tree
I would like to generate a complete parse tree, that allows you to manipulate
the data structure and also dump it, including all whitespaces and comments.
The spec says that this is throwaway content, but I read that many people
wish to be able to keep the comments.
=back
=head2 YAML::PP::Dumper, YAML::PP::Emitter
The Dumper should be able to dump strings correctly, adding quotes
whenever a plain scalar would look like a special string, like C<true>,
or when it contains or starts with characters that are not allowed.
Most strings will be dumped as plain scalars without quotes. If they
contain special characters or have a special meaning, they will be dumped
with single quotes. If they contain control characters, including <"\n">,
they will be dumped with double quotes.
It will recognize JSON::PP::Boolean and boolean.pm objects and dump them
correctly.
Numbers which also have a C<PV> flag will be recognized as numbers and not
as strings:
my $int = 23;
say "int: $int"; # $int will now also have a PV flag
That means that if you accidentally use a string in numeric context, it will
also be recognized as a number:
my $string = "23";
my $something = $string + 0;
print $yp->dump_string($string);
# will be emitted as an integer without quotes!
The layout is like libyaml output:
key:
- a
- b
- c
---
- key1: 1
key2: 2
key3: 3
---
- - a1
- a2
- - b1
- b2
=head1 WHY
All the available parsers and loaders for Perl are behaving differently,
and more important, aren't conforming to the spec. L<YAML::XS> is
doing pretty well, but C<libyaml> only handles YAML 1.1 and diverges
a bit from the spec. The pure perl loaders lack support for a number of
features.
I was going over L<YAML>.pm issues end of 2016, integrating old patches
from rt.cpan.org and creating some pull requests myself. I realized
that it would be difficult to patch YAML.pm to parse YAML 1.1 or even 1.2,
and it would also break existing usages relying on the current behaviour.
( run in 1.323 second using v1.01-cache-2.11-cpan-39bf76dae61 )