Skip to content

Commit

Permalink
Polish Proc methods that expect the Proc to be done
Browse files Browse the repository at this point in the history
Affects methods .status, .Numeric, .Bool, .exitcode, and .sink.
Fixes module build installation failures and RT#125757:
https://rt.perl.org/Ticket/Display.html?id=125757#ticket-history

Even before Proc refactor, we had some issues where users would call, say,
.exitcode, and expect the exitcode, but .out/.err pipes were still open,
so the .exitcode was wrong.

The Proc refactor exacerbated the issue, as now the user had to ensure the
opened pipes were closed when a call to one of the affected methods listed
above were made or a Proc was sunk.

Fix by waiting for the proc to finish up when any of the affected methods
are called. The one extra thing we can do is also close .stdin of the proc,
but I'm not 100% sure if we should. Also, the current method is a bit fragile,
in that setting $exitcode when instantiating the Proc to anything but -1
will not await for proc to be completed and won't update the exitcode...
  • Loading branch information
zoffixznet committed Jun 15, 2017
1 parent 14d7571 commit e4468c6
Showing 1 changed file with 36 additions and 19 deletions.
55 changes: 36 additions & 19 deletions src/core/Proc.pm
Expand Up @@ -108,49 +108,66 @@ my class Proc {
} }


method !await-if-last-handle(--> Nil) { method !await-if-last-handle(--> Nil) {
$!active-handles--; self!wait-for-finish unless --$!active-handles;
if $!active-handles == 0 {
self.status(await($!finished).status);
CATCH { default { self.status(0x100) } }
}
} }


method spawn(*@args where .so, :$cwd = $*CWD, :$env) { method !wait-for-finish {
CATCH { default { self.status(0x100) } }
self.status(await($!finished).status) if $!exitcode == -1;
}

method spawn(*@args where .so, :$cwd = $*CWD, :$env --> Bool:D) {
@!command = @args; @!command = @args;
my %env := $env ?? $env.hash !! %*ENV; self!spawn-internal(@args, $cwd, $env)
self!spawn-internal(@args, $cwd, %env)
} }


method shell($cmd, :$cwd = $*CWD, :$env) { method shell($cmd, :$cwd = $*CWD, :$env --> Bool:D) {
@!command = $cmd; @!command = $cmd;
my %env := $env ?? $env.hash !! %*ENV;
my @args := Rakudo::Internals.IS-WIN my @args := Rakudo::Internals.IS-WIN
?? (%*ENV<ComSpec>, '/c', $cmd) ?? (%*ENV<ComSpec>, '/c', $cmd)
!! ('/bin/sh', '-c', $cmd); !! ('/bin/sh', '-c', $cmd);
self!spawn-internal(@args, $cwd, %env) self!spawn-internal(@args, $cwd, $env)
} }


method !spawn-internal(@args, $cwd, %ENV) { method !spawn-internal(@args, $cwd, $env --> Bool:D) {
my %ENV := $env ?? $env.hash !! %*ENV;
$!proc := Proc::Async.new(|@args, :$!w); $!proc := Proc::Async.new(|@args, :$!w);
.() for @!pre-spawn; .() for @!pre-spawn;
$!finished = $!proc.start(:$cwd, :%ENV, scheduler => $PROCESS::SCHEDULER); $!finished = $!proc.start(:$cwd, :%ENV, scheduler => $PROCESS::SCHEDULER);
unless $!in || $!out || $!err { my $is-spawned := do {
self.status(await($!finished).status);
CATCH { default { self.status(0x100) } } CATCH { default { self.status(0x100) } }
} await $!proc.ready;
self.Bool True
} // False;
.() for @!post-spawn;
self!wait-for-finish unless $!out || $!err || $!in;
$is-spawned
} }


proto method status(|) { * } proto method status(|) { * }
multi method status($new_status) { multi method status($new_status) {
$!exitcode = $new_status +> 8; $!exitcode = $new_status +> 8;
$!signal = $new_status +& 0xFF; $!signal = $new_status +& 0xFF;
} }
multi method status(Proc:D:) { ($!exitcode +< 8) +| $!signal } multi method status(Proc:D:) {
multi method Numeric(Proc:D:) { $!exitcode } self!wait-for-finish;
multi method Bool(Proc:D:) { $!exitcode == 0 } ($!exitcode +< 8) +| $!signal
}
multi method Numeric(Proc:D:) {
self!wait-for-finish;
$!exitcode
}
multi method Bool(Proc:D:) {
self!wait-for-finish;
$!exitcode == 0
}
method exitcode {
self!wait-for-finish;
$!exitcode
}


method sink(--> Nil) { method sink(--> Nil) {
self!wait-for-finish;
X::Proc::Unsuccessful.new(:proc(self)).throw if $!exitcode > 0; X::Proc::Unsuccessful.new(:proc(self)).throw if $!exitcode > 0;
} }
} }
Expand Down

0 comments on commit e4468c6

Please sign in to comment.