On Fri, 03 Feb 2017 18:27:34 -0800, comdog wrote:
> While trying to work around #125757 (using :out
> makes the Proc object always return zero, I ran
> into a different problem. I was writing test code
> to check what a program does in cases where it
> should exit with a non-zero status.
> 
> The docs for IO::Handle::close say only:
> 
>     Will close a previously opened filehandle.
> 
> But other close methods mention using a LEAVE
> phaser to avoid exceptions. I end up with kludgey
> code like this to fight against Perl 6 thinking it
> knows better than I do when something failed:
> 
>     subtest {
>         my $proc = run $*EXECUTABLE, $program, '-k', :err;
>         my $message = try { $proc.err.slurp-rest };
>         LEAVE { quietly { $proc.err.close  } }
> 
>         like $message, rx:i/invalid/, 'Invalid option warns';
>         is $proc.exitcode, 2, 'exit code';
>         }, "{$program} exits with false value with unknown switch";
> 
> Now, indeed this returned a non-zero exit status.
> But, it did exactly what I wanted it to. This
> isn't a failure in my code and it shouldn't be
> exceptional.
> 
> Beyond that, there are many programs that use a
> non-zero exit to mean something that isn't
> failure. grep(1), for instance, uses 1 to mean no
> lines matched. And so on. Perl 6 doesn't know
> these, and I don't think it should make decisions
> at this level.
> 
> I wouldn't mind the ability to throw an exception
> if Proc was told to do that (say, like
> :raise-exception similar to DBI's RaiseError).
> But, it's easy enough for the programmer to make
> this call on their own.


Thank you for the report. However, I'm going to reject this ticket, as
the described issue is just a misunderstanding and does not exist:

- "IO::Handle::close shouldn't decide what's a failure"
    - It doesn't. The explosion you show is due to a sunk Proc object.
- "The docs for IO::Handle::close say"
    - Those are the wrong docs. The code you show calls .close on IO::Pipe.
      While IO::Pipe is IO::Handle, it provides its own close method[^1]
      that returns the Pipe's Proc object
- "But other close methods mention using a LEAVE phaser to avoid exceptions"
    - The now-reworded[^2] docs meant you could use LEAVE phaser to close
      a handle on scope leave, regardless of whether it's left normally or via
      a thrown exception (in the latter case, a .close at the end of the block
      wouldn't be reached). This isn't about *avoiding* any exceptions.
- "close shouldn't decide what's a failure"
    - It doesn't. Your .close returns the Proc object, which throws when sunk,
      if the process had non-zero status. There are no exceptions or failures
      involved in .close itself, so to avoid the explosion simply ensure the
      Proc doesn't get sunk
- "I end up with kludgey code"
    - You can close the Pipe via an arg given to .slurp (or .slurp-rest
      if you're on older Rakudos; will be deprecated in 6.d and removed in 6.e).
      And since the .close doesn't throw and we don't sink any Procs, no
      explosions happen and the code isn't kludgy:

        use Test;
        my $program = ('-e', 'die "invalid"', '--');
        subtest {
            with run :err, $*EXECUTABLE, |$program, '-y' {
                like .err.slurp(:close), rx:i/invalid/, 'Invalid option warns';
                is   .exitcode,          1,             'exit code';
            }
        }, "{$program} exits with false value with unknown switch";

[1] https://docs.perl6.org/type/IO::Pipe#method_close
[2] https://github.com/perl6/doc/commit/2387ce3518aa29fb198e6c5bb77991f3b307f091

-- IO grant

Reply via email to