File Coverage

blib/lib/Mojo/Phantom/Process.pm
Criterion Covered Total %
statement 18 40 45.0
branch 1 4 25.0
condition 0 3 0.0
subroutine 5 9 55.5
pod 2 2 100.0
total 26 58 44.8


line stmt bran cond sub pod time code
1             package Mojo::Phantom::Process;
2              
3 8     8   31 use Mojo::Base 'Mojo::EventEmitter';
  8         14  
  8         54  
4              
5 8     8   1318 use constant DEBUG => $ENV{MOJO_PHANTOM_DEBUG};
  8         10  
  8         595  
6              
7 8     8   33 use Mojo::IOLoop;
  8         25  
  8         79  
8 8     8   195 use Mojo::IOLoop::Stream;
  8         12  
  8         71  
9              
10             has [qw/error exit_status pid stream/];
11             has arguments => sub { [] };
12              
13             has exe => 'phantomjs';
14              
15             sub kill {
16 0     0 1 0 my ($self) = @_;
17 0 0       0 return unless my $pid = $self->pid;
18 0         0 warn "Killing $pid\n" if DEBUG;
19 0         0 kill KILL => $pid;
20 0         0 waitpid $pid, 0;
21 0         0 $self->exit_status($?);
22 0         0 $self->stream->close;
23             };
24              
25             sub start {
26 12     12 1 24 my ($self, $file) = @_;
27              
28 12         51 my @command = ($self->exe, @{ $self->arguments }, "$file");
  12         90  
29 12         167 warn 'Spawning: ' . (join ', ', map { "'$_'" } @command) . "\n" if DEBUG;
30 12         36218 my $pid = open my $pipe, '-|', @command;
31 12 50       1444 die 'Could not spawn' unless defined $pid;
32 0           $self->pid($pid);
33 0           $self->emit(spawn => $pid);
34              
35 0           my $stream = Mojo::IOLoop::Stream->new($pipe);
36 0           my $id = Mojo::IOLoop->stream($stream);
37 0           $self->stream($stream);
38 0     0     $stream->on(error => sub { $self->error($_[1])->kill });
  0            
39 0     0     $stream->on(read => sub { $self->emit(read => $_[1]) });
  0            
40             $stream->on(close => sub {
41 0     0     my $pid = delete $self->{pid};
42 0           warn "Stream for $pid closed\n" if DEBUG;
43 0   0       $self->{exit_status} ||= $?;
44 0           $self->emit('close');
45 0           });
46              
47 0           return $self;
48             }
49              
50             1;
51              
52             =head1 NAME
53              
54             Mojo::Phantom::Process - Represents the running phantom process and its stream
55              
56             =head1 SYNOPSIS
57              
58             my $proc = Mojo::Phantom::Process->new;
59             $proc->start($file);
60              
61             =head1 DESCRIPTION
62              
63             A very utilitarian class representing a single execution of the PhantomJS executable.
64             It forks the new process and attaches a stream watcher to its STDOUT and attaches to various stream events.
65             This class is just process management and transport.
66             All real behavior is defined by the executed javascript file and the listeners to the events defined by this class.
67              
68             =head1 EVENTS
69              
70             L inherits all the events from L and emits the following new ones
71              
72             =head2 close
73              
74             $proc->on(close => sub { ($proc) = @_; ... });
75              
76             Emitted when the process has exitted (possibly with errors) and the stream has closed.
77             The user will want to check L and L.
78              
79             =head2 read
80              
81             $proc->on(read => sub { ($proc, $bytes) = @_; ... });
82              
83             Re-emitted after bytes have been read from the L.
84              
85             =head2 spawn
86              
87             $proc->on(spawn => sub { my ($proc, $pid) = @_; ... });
88              
89             Emitted just after the child process is spawned.
90             Passed the new child pid.
91              
92             =head1 ATTRIBUTES
93              
94             =head2 arguments
95              
96             Holds an array reference of arguments passed directly to the PhantomJS executable when it is run.
97              
98             my @phantom_args = ('--proxy=127.0.0.1:8080', '--proxy-type='socks5');
99             my $proc = Mojo::Phantom::Process->new(arguments => \@phantom_args);
100              
101             =head2 error
102              
103             Holds errors caught from the L's error event.
104             Note that when such an error event is caught, the process is then killed by the L method immediately afterwards.
105              
106             =head2 exit_status
107              
108             The exit status C<$?> from the closed pid.
109              
110             =head2 pid
111              
112             The pid of the spawned process.
113             The stream's close event will clear this value once the process has ended.
114              
115             =head2 stream
116              
117             The instance of L used to monitor the STDOUT of the external process.
118             It is created automatically attacted to the L by running L.
119              
120             =head2 exe
121              
122             The executable name or path to call PhantomJS. You may substitute a compatible platform, for example using C to use
123             CasperJS.
124              
125             =head1 METHODS
126              
127             =head2 kill
128              
129             $proc->kill
130              
131             Kills the child process (KILL) and closes the stream.
132             Note that since the process might exit before the kill signal is sent, it is not guaranteed that the L will reflect the signal.
133              
134             =head2 start
135              
136             $proc->start($file);
137              
138             Starts a PhantomJS in a child process running a given file, creates a stream listener and attaches to its events.
139             Returns itself.
140