1package AnyEvent::Subprocess::Running;
2BEGIN {
3  $AnyEvent::Subprocess::Running::VERSION = '1.102912';
4}
5# ABSTRACT: represents a running subprocess
6use Moose;
7use Event::Join;
8
9use AnyEvent;
10use AnyEvent::Subprocess::Done;
11use AnyEvent::Subprocess::Types qw(RunDelegate);
12
13with 'AnyEvent::Subprocess::Role::WithDelegates' => {
14    type => RunDelegate,
15};
16
17# we have to set this "later"
18has 'child_pid' => (
19    is  => 'rw',
20    isa => 'Int',
21    trigger => sub {
22        my ($self, $pid) = @_;
23        $self->child_listener if defined $pid;
24    },
25);
26
27has 'child_listener' => (
28    is      => 'ro',
29    lazy    => 1,
30    clearer => 'cleanup_child_watcher',
31    default => sub {
32        my $self = shift;
33        confess 'child_listener being built too early'
34          unless $self->child_pid;
35
36        my $child_listener = AnyEvent->child(
37            pid => $self->child_pid,
38            cb => sub {
39                my ($pid, $status) = @_;
40                $self->child_event_joiner->send_event( child => $status );
41                $self->cleanup_child_watcher;
42            },
43        );
44        return $child_listener;
45    }
46);
47
48has 'on_completion' => (
49    is       => 'ro',
50    isa      => 'CodeRef',
51    default  => sub { sub {} },
52    required => 1,
53);
54
55has 'child_events' => (
56    is      => 'ro',
57    isa     => 'ArrayRef[Str]',
58    lazy    => 1,
59    builder => '_build_child_events',
60);
61
62sub _build_child_events {
63    my $self = shift;
64    return [qw/child/, $self->_invoke_delegates('build_events')];
65}
66
67has 'child_event_joiner' => (
68    is       => 'ro',
69    isa      => 'Event::Join',
70    lazy     => 1,
71    default  => sub {
72        my $self = shift;
73        my $joiner = Event::Join->new(
74            events        => $self->child_events,
75            on_completion => sub {
76                my $events = shift;
77                my $status = $events->{child};
78
79                $self->_completion_hook(
80                    events => $events,
81                    status => $status,
82                );
83            }
84        );
85
86        for my $d ($self->_delegates){
87            my %events = map { $_ => $joiner->event_sender_for($_) } $d->build_events;
88            $d->event_senders(\%events);
89        }
90
91        return $joiner;
92    },
93);
94
95sub _completion_hook {
96    my ($self, %args) = @_;
97    my $status = $args{status};
98
99    my $done = AnyEvent::Subprocess::Done->new(
100        delegates   => [$self->_invoke_delegates('build_done_delegates')],
101        exit_status => $status,
102    );
103
104    $args{done} = $done;
105    $args{run} = $self;
106    $self->_invoke_delegates('completion_hook', \%args);
107    $self->on_completion->($done);
108}
109
110sub kill {
111    my $self = shift;
112    my $signal = shift || 9;
113
114    kill $signal, $self->child_pid; # BAI
115}
116
117sub BUILD {
118    my $self = shift;
119    $self->child_event_joiner; # vivify
120}
121
122__PACKAGE__->meta->make_immutable;
123
1241;
125
126
127
128=pod
129
130=head1 NAME
131
132AnyEvent::Subprocess::Running - represents a running subprocess
133
134=head1 VERSION
135
136version 1.102912
137
138=head1 SYNOPSIS
139
140We are C<$run> in a sequence like:
141
142   my $job = AnyEvent::Subprocess->new ( ... );
143   my $run = $job->run;
144   $run->delegate('stdin')->push_write('Hello, my child!');
145   say "Running child as ", $run->child_pid;
146   $run->kill(11) if $you_enjoy_that_sort_of_thing;
147   my $done = $job->delegate('completion_condvar')->recv;
148   say "Child exited with signal ", $done->exit_signal;
149
150=head1 DESCRIPTION
151
152An instance of this class is returned when you start a subprocess.  It
153contains the child pid, any delegates that operate on the running
154subprocess (handles, captures, etc.), and some control methods.
155
156=head1 METHODS
157
158=head2 child_pid
159
160Returns the pid of the child
161
162=head2 kill($signal)
163
164Kills the child with signal number C<$signal>
165
166=head2 delegate($name)
167
168Returns the delegate named C<$name>
169
170=head1 SEE ALSO
171
172L<AnyEvent::Subprocess>
173
174L<AnyEvent::Subprocess::Role::WithDelegates>
175
176=head1 AUTHOR
177
178Jonathan Rockway <jrockway@cpan.org>
179
180=head1 COPYRIGHT AND LICENSE
181
182This software is copyright (c) 2011 by Jonathan Rockway.
183
184This is free software; you can redistribute it and/or modify it under
185the same terms as the Perl 5 programming language system itself.
186
187=cut
188
189
190__END__
191
192