File Coverage

blib/lib/Reflex/POE/Wheel/Run.pm
Criterion Covered Total %
statement 34 36 94.4
branch n/a
condition n/a
subroutine 14 15 93.3
pod 3 7 42.8
total 51 58 87.9


line stmt bran cond sub pod time code
1             package Reflex::POE::Wheel::Run;
2             # vim: ts=2 sw=2 noexpandtab
3             $Reflex::POE::Wheel::Run::VERSION = '0.100';
4 1     1   362548 use Moose;
  1         1  
  1         5  
5             extends 'Reflex::POE::Wheel';
6 1     1   5270 use POE::Wheel::Run;
  1         110050  
  1         30  
7 1     1   489 use Reflex::PID;
  1         4  
  1         44  
8 1     1   556 use Reflex::Trait::Watched qw(watches);
  1         3  
  1         3  
9              
10             # TODO - Bored now. use Reflex::Event qw(Flushed Octets Error EOF); ???
11              
12 1     1   757 use Reflex::Event::Flushed;
  1         3  
  1         34  
13 1     1   563 use Reflex::Event::Octets;
  1         3  
  1         36  
14 1     1   581 use Reflex::Event::Error;
  1         3  
  1         45  
15 1     1   574 use Reflex::Event::EOF;
  1         3  
  1         326  
16              
17             # These are class methods, returning static class data.
18             # TODO - What's the proper way to do this with Moose?
19              
20             my %event_to_index = (
21             StdinEvent => 0,
22             StdoutEvent => 1,
23             StderrEvent => 2,
24             ErrorEvent => 3,
25             CloseEvent => 4,
26             );
27              
28             sub events_to_indices {
29 2     2 0 5 return \%event_to_index;
30             }
31              
32             my @index_to_event = (
33             [ 'Reflex::Event::Flushed', 'stdin', 'wheel_id' ],
34             [ 'Reflex::Event::Octets', 'stdout', 'octets', 'wheel_id' ],
35             [ 'Reflex::Event::Octets', 'stderr', 'octets', 'wheel_id' ],
36             [
37             'Reflex::Event::Error', 'error', 'function', 'number', 'string', 'wheel_id'
38             ],
39             [ 'Reflex::Event::EOF', 'closed', 'wheel_id' ],
40             );
41              
42             sub index_to_event {
43 17     17 0 21 my ($class, $index) = @_;
44 17         18 return @{$index_to_event[$index]};
  17         72  
45             }
46              
47             sub wheel_class {
48 2     2 1 5 return 'POE::Wheel::Run';
49             }
50              
51             sub valid_params {
52             return(
53             {
54 14     14 1 97 CloseOnCall => 1,
55             Conduit => 1,
56             Filter => 1,
57             Group => 1,
58             NoSetPgrp => 1,
59             NoSetSid => 1,
60             Priority => 1,
61             Program => 1,
62             ProgramArgs => 1,
63             StderrDriver => 1,
64             StderrFilter => 1,
65             StdinDriver => 1,
66             StdinFilter => 1,
67             StdioDriver => 1,
68             StdioFilter => 1,
69             StdoutDriver => 1,
70             StdoutFilter => 1,
71             User => 1,
72             }
73             );
74             }
75              
76             # Also handle signals.
77              
78             watches sigchild_watcher => (
79             isa => 'Maybe[Reflex::PID]',
80             role => 'sigchld',
81             );
82              
83             sub BUILD {
84 2     2 0 5 my $self = shift;
85              
86 2         64 $self->sigchild_watcher(
87             Reflex::PID->new(pid => $self->wheel()->PID())
88             );
89             }
90              
91             # Rethrow our signal event.
92             sub on_sigchld_exit {
93 2     2 0 3 my ($self, $event) = @_;
94 2         14 $self->re_emit( $event, -name => 'signal' );
95             }
96              
97             sub kill {
98 0     0 1   my $self = shift;
99 0           $self->wheel()->kill(@_);
100             }
101              
102             __PACKAGE__->meta->make_immutable;
103              
104             1;
105              
106             __END__
107              
108             =pod
109              
110             =encoding UTF-8
111              
112             =for :stopwords Rocco Caputo
113              
114             =head1 NAME
115              
116             Reflex::POE::Wheel::Run - Represent POE::Wheel::Run as a Reflex class.
117              
118             =head1 VERSION
119              
120             This document describes version 0.100, released on April 02, 2017.
121              
122             =head1 SYNOPSIS
123              
124             Unfortunately there isn't a concise, completely executable example for
125             the synopsis at this time. Please see eg-07-wheel-run.pl and
126             eg-08-watched-trait.pl in the distribution's eg directory for longer
127             but fully executable ones.
128              
129             watches child => (
130             isa => 'Reflex::POE::Wheel::Run|Undef',
131             );
132              
133             sub BUILD {
134             my $self = shift;
135             $self->child(
136             Reflex::POE::Wheel::Run->new(
137             Program => "$^X -wle 'print qq[pid(\$\$) moo(\$_)] for 1..10; exit'",
138             )
139             );
140             }
141              
142             sub on_child_stdout {
143             my ($self, $event) = @_;
144             print "stdout: ", $event->output(), "\n";
145             }
146              
147             sub on_child_close {
148             my ($self, $event) = @_;
149             print "child closed all output\n";
150             }
151              
152             sub on_child_signal {
153             my ($self, $event) = @_;
154             print "child ", $event->pid(), " exited: ", $event->exit(), "\n";
155             $self->child(undef);
156             }
157              
158             =head1 DESCRIPTION
159              
160             Reflex::POE::Wheel::Run represents an enhanced POE::Wheel::Run object.
161             It will manage a child process, and it will also wait for (and report
162             on) the corresponding SIGCHLD.
163              
164             This module delegates to L<POE::Wheel::Run> for most of its
165             implementation. Please refer to that module for implementation
166             details.
167              
168             =head2 Public Methods
169              
170             This class adds public methods specific to POE::Wheel::Run's
171             operation. However, common methods like put() are both implemented
172             and documented in the base L<Reflex::POE::Wheel> class.
173              
174             =head3 kill
175              
176             kill() passes its arguments to POE::Wheel::Run's kill() method.
177              
178             =head2 Public Events
179              
180             Objects of this class emit all of POE::Wheel::Run's events, albeit
181             renamed into Reflex-friendly forms. Generally these forms are
182             determined by removing the "Event" suffix and lowercasing what
183             remains. POE::Wheel::Run's StdinEvent becomes "stdin", and so on.
184              
185             =head3 stdin
186              
187             See POE::Wheel::Run's StdinEvent. Within Reflex, this event comes
188             with only one parameter: "wheel_id". This is the POE::Wheel::Run
189             object's ID.
190              
191             =head3 stdout
192              
193             See POE::Wheel::Run's StdoutEvent. Reflex includes two parameters:
194             "wheel_id" and "output". The latter parameter contains data the child
195             process wrote to its STDOUT handle.
196              
197             =head3 stderr
198              
199             See POE::Wheel::Run's StderrEvent. Reflex includes two parameters:
200             "wheel_id" and "output". The latter parameter contains data the child
201             process wrote to its STDERR handle.
202              
203             =head3 error
204              
205             See POE::Wheel::Run's ErrorEvent. Reflex maps the wheel's parameters
206             to: "operation", "errnum", "errstr", "wheel_id" and "handle_name",
207             respectively.
208              
209             =head3 closed
210              
211             See POE::Wheel::Run's CloseEvent. Reflex includes only one parameter
212             for this event: "wheel_id".
213              
214             =for Pod::Coverage BUILD events_to_indices index_to_event on_sigchld_exit
215              
216             =head1 CAVEATS
217              
218             This class could further be improved so that it doesn't report SIGCHLD
219             until all the child's output has been received and processed. This
220             would resolve a long-standing nondeterminism in the timing of
221             on_child_close() vs. on_child_signal().
222              
223             =head1 SEE ALSO
224              
225             Please see those modules/websites for more information related to this module.
226              
227             =over 4
228              
229             =item *
230              
231             L<Reflex|Reflex>
232              
233             =item *
234              
235             L<Moose::Manual::Concepts>
236              
237             =item *
238              
239             L<Reflex>
240              
241             =item *
242              
243             L<Reflex::POE::Event>
244              
245             =item *
246              
247             L<Reflex::POE::Postback>
248              
249             =item *
250              
251             L<Reflex::POE::Session>
252              
253             =item *
254              
255             L<Reflex::POE::Wheel>
256              
257             =item *
258              
259             L<Reflex/ACKNOWLEDGEMENTS>
260              
261             =item *
262              
263             L<Reflex/ASSISTANCE>
264              
265             =item *
266              
267             L<Reflex/AUTHORS>
268              
269             =item *
270              
271             L<Reflex/BUGS>
272              
273             =item *
274              
275             L<Reflex/BUGS>
276              
277             =item *
278              
279             L<Reflex/CONTRIBUTORS>
280              
281             =item *
282              
283             L<Reflex/COPYRIGHT>
284              
285             =item *
286              
287             L<Reflex/LICENSE>
288              
289             =item *
290              
291             L<Reflex/TODO>
292              
293             =back
294              
295             =head1 BUGS AND LIMITATIONS
296              
297             You can make new bug reports, and view existing ones, through the
298             web interface at L<http://rt.cpan.org/Public/Dist/Display.html?Name=Reflex>.
299              
300             =head1 AUTHOR
301              
302             Rocco Caputo <rcaputo@cpan.org>
303              
304             =head1 COPYRIGHT AND LICENSE
305              
306             This software is copyright (c) 2017 by Rocco Caputo.
307              
308             This is free software; you can redistribute it and/or modify it under
309             the same terms as the Perl 5 programming language system itself.
310              
311             =head1 AVAILABILITY
312              
313             The latest version of this module is available from the Comprehensive Perl
314             Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN
315             site near you, or see L<https://metacpan.org/module/Reflex/>.
316              
317             =head1 DISCLAIMER OF WARRANTY
318              
319             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
320             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
321             WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
322             PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
323             EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
324             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
325             PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
326             SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME
327             THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
328              
329             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
330             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
331             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
332             TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
333             CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
334             SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
335             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
336             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
337             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
338             DAMAGES.
339              
340             =cut