aboutsummaryrefslogtreecommitdiff
path: root/lib/App/Beam/Command.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/App/Beam/Command.pm')
-rw-r--r--lib/App/Beam/Command.pm44
1 files changed, 39 insertions, 5 deletions
diff --git a/lib/App/Beam/Command.pm b/lib/App/Beam/Command.pm
index 79b8b06..4f92cdf 100644
--- a/lib/App/Beam/Command.pm
+++ b/lib/App/Beam/Command.pm
@@ -12,6 +12,7 @@ our %EXPORT_TAGS = (
use IPC::Open3;
use Symbol 'gensym';
+use POSIX qw(:sys_wait_h);
sub new {
my $class = shift;
@@ -28,6 +29,24 @@ use constant {
CHAN_STDERR => 1
};
+sub start_log {
+ my ($self, $chan, $rfd) = @_;
+
+ if (exists($self->{log}) && defined($self->{log}[$chan])) {
+ local $^F = fileno($rfd);
+ my $pid = fork();
+ if ($pid == 0) {
+ local $_ = $rfd;
+ &{$self->{log}[CHAN_STDERR]};
+ exit(0);
+ } else {
+ push @{$self->{pids}}, $pid;
+ return undef;
+ }
+ }
+ return $rfd;
+}
+
sub run {
my $self = shift;
my $out = gensym;
@@ -36,25 +55,39 @@ sub run {
return $self->{status} if exists($self->{status});
eval {
- my $pid = open3(\*STDIN, $out, $err, @{$self->{argv}});
- waitpid($pid, 0);
+ push @{$self->{pids}},
+ open3(\*STDIN, $out, $err, @{$self->{argv}});
+ $out = $self->start_log(CHAN_STDOUT, $out);
+ $err = $self->start_log(CHAN_STDERR, $err);
+ do {
+ my $pid = waitpid(-1, 0);
+ if ($pid > 0) {
+ @{$self->{pids}} = grep { $pid != $_ } @{$self->{pids}};
+ }
+ } while ($#{$self->{pids}} >= 0);
};
if ($@) {
$self->{status} = $@;
} else {
$self->{status} = $?;
local $/ = undef;
- $self->{channel}[CHAN_STDOUT] = <$out>;
- $self->{channel}[CHAN_STDERR] = <$err>;
+ $self->{channel}[CHAN_STDOUT] = defined($out) ? <$out> : undef;
+ $self->{channel}[CHAN_STDERR] = defined($err) ? <$err> : undef;
}
return $self->{status};
}
+sub set_logger {
+ my ($self, $chan, $fun) = @_;
+ $self->{log}[$chan] = $fun;
+}
+
sub restart {
my $self = shift;
delete $self->{status};
delete $self->{channel};
+ delete $self->{pids};
return $self->run;
}
@@ -66,7 +99,8 @@ sub status {
sub channel {
my ($self, $chan) = @_;
- return undef if !exists($self->{channel}) || $chan > $#{$self->{channel}};
+ return undef
+ unless (exists($self->{channel}) && defined($self->{channel}[$chan]));
open(my $fd, '<', \$self->{channel}[$chan]) or croak "can't dup: $!";
return $fd;
}

Return to:

Send suggestions and report system problems to the System administrator.