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