line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
AnyEvent::Fork::Remote - remote processes with AnyEvent::Fork interface |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
THE API IS NOT FINISHED, CONSIDER THIS A BETA RELEASE |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use AnyEvent; |
10
|
|
|
|
|
|
|
use AnyEvent::Fork::Remote; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my $rpc = AnyEvent::Fork::Remote |
13
|
|
|
|
|
|
|
->new_execp ("ssh", "ssh", "othermachine", "perl") |
14
|
|
|
|
|
|
|
->require ("MyModule") |
15
|
|
|
|
|
|
|
->run ("MyModule::run", my $cv = AE::cv); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
my $fh = $cv->recv; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 DESCRIPTION |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Despite what the name of this module might suggest, it doesn't actually |
22
|
|
|
|
|
|
|
create remote processes for you. But it does make it easy to use them, |
23
|
|
|
|
|
|
|
once you have started them. |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
This module implements a very similar API as L. In fact, |
26
|
|
|
|
|
|
|
similar enough to require at most minor modifications to support both |
27
|
|
|
|
|
|
|
at the same time. For example, it works with L and |
28
|
|
|
|
|
|
|
L. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
The documentation for this module will therefore only document the parts |
31
|
|
|
|
|
|
|
of the API that differ between the two modules. |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head2 SUMMARY OF DIFFERENCES |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
Here is a short summary of the main differences between L |
36
|
|
|
|
|
|
|
and this module: |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=over 4 |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=item * C is not implemented and will fail |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=item * the child-side C function must read from STDIN and write to STDOUT |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=item * C does not actually fork, but will create a new process |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=back |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 EXAMPLE |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
This example uses a local perl (because that is likely going to work |
51
|
|
|
|
|
|
|
without further setup) and the L to create simple |
52
|
|
|
|
|
|
|
worker process. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
First load the modules we are going to use: |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
use AnyEvent; |
57
|
|
|
|
|
|
|
use AnyEvent::Fork::Remote; |
58
|
|
|
|
|
|
|
use AnyEvent::Fork::RPC; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Then create, configure and run the process: |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
my $rpc = AnyEvent::Fork::Remote |
63
|
|
|
|
|
|
|
->new_execp ("perl", "perl") |
64
|
|
|
|
|
|
|
->eval (' |
65
|
|
|
|
|
|
|
sub myrun { |
66
|
|
|
|
|
|
|
"this is process $$, and you passed <@_>" |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
') |
69
|
|
|
|
|
|
|
->AnyEvent::Fork::RPC::run ("myrun"); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
We use C to execute the first F found in the PATH. You'll |
72
|
|
|
|
|
|
|
have to make sure there is one for this to work. The perl does not |
73
|
|
|
|
|
|
|
actually have to be the same perl as the one running the example, and it |
74
|
|
|
|
|
|
|
doesn't need to have any modules installed. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
The reason we have to specif< C twice is that the first argument to |
77
|
|
|
|
|
|
|
C (and also C) is the program name or path, while |
78
|
|
|
|
|
|
|
the remaining ones are the arguments, and the first argument passed to a |
79
|
|
|
|
|
|
|
program is the program name, so it has to be specified twice. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Finally, the standard example, send some numbers to the remote function, |
82
|
|
|
|
|
|
|
and print whatever it returns: |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
my $cv = AE::cv; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
for (1..10) { |
87
|
|
|
|
|
|
|
$cv->begin; |
88
|
|
|
|
|
|
|
$rpc->($_, sub { |
89
|
|
|
|
|
|
|
print "remote function returned: $_[0]\n"; |
90
|
|
|
|
|
|
|
$cv->end; |
91
|
|
|
|
|
|
|
}); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
$cv->recv; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
Now, executing F in the PATH isn't very interesting - you could have |
97
|
|
|
|
|
|
|
done the same with L, and it might even be more efficient. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
The power of this module is that the F doesn't need to run on the |
100
|
|
|
|
|
|
|
local box, you could simply substitute another command, such as F
|
101
|
|
|
|
|
|
|
remotebox perl>: |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
my $rpc = AnyEvent::Fork::Remote |
104
|
|
|
|
|
|
|
->new_execp ("ssh", "ssh", "remotebox", "perl") |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
And if you want to use a specific path for ssh, use C: |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
my $rpc = AnyEvent::Fork::Remote |
109
|
|
|
|
|
|
|
->new_exec ("/usr/bin/ssh", "ssh", "remotebox", "perl") |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Of course, it doesn't really matter to this module how you construct your |
112
|
|
|
|
|
|
|
perl processes, what matters is that somehow, you give it a file handle |
113
|
|
|
|
|
|
|
connected to the new perls STDIN and STDOUT. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 PARENT PROCESS USAGE |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=over 4 |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=cut |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
package AnyEvent::Fork::Remote; |
122
|
|
|
|
|
|
|
|
123
|
2
|
|
|
2
|
|
35369
|
use common::sense; |
|
2
|
|
|
|
|
22
|
|
|
2
|
|
|
|
|
13
|
|
124
|
|
|
|
|
|
|
|
125
|
2
|
|
|
2
|
|
130
|
use Carp (); |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
40
|
|
126
|
2
|
|
|
2
|
|
1640
|
use Errno (); |
|
2
|
|
|
|
|
1880
|
|
|
2
|
|
|
|
|
50
|
|
127
|
|
|
|
|
|
|
|
128
|
2
|
|
|
2
|
|
2289
|
use AnyEvent (); |
|
2
|
|
|
|
|
5164
|
|
|
2
|
|
|
|
|
3732
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
our $VERSION = 0.2; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# xored together must start and and with \n |
133
|
|
|
|
|
|
|
my $magic0 = "Pdk{6y[_zZ"; |
134
|
|
|
|
|
|
|
my $magic1 = "Z^yZ7~i=oP"; |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item my $proc = new_exec AnyEvent::Fork::Remote $path, @args... |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Creates a new C object. Unlike L, |
139
|
|
|
|
|
|
|
processes are only created when C is called, every other method call |
140
|
|
|
|
|
|
|
is is simply recorded until then. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Each time a new process is needed, it executes C<$path> with the given |
143
|
|
|
|
|
|
|
arguments (the first array member must be the program name, as with |
144
|
|
|
|
|
|
|
the C function with explicit PROGRAM argument) and both C |
145
|
|
|
|
|
|
|
and C connected to a communications socket. No input must be |
146
|
|
|
|
|
|
|
consumed by the command before F is started, and no output should be |
147
|
|
|
|
|
|
|
generated. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
The program I invoke F somehow, with STDIN and STDOUT intact, |
150
|
|
|
|
|
|
|
without specifying anything to execute (no script file name, no C<-e> |
151
|
|
|
|
|
|
|
switch etc.). |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Here are some examples to give you an idea: |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# just "perl" |
156
|
|
|
|
|
|
|
$proc = new_exec AnyEvent::Fork::Remote |
157
|
|
|
|
|
|
|
"/usr/bin/perl", "perl"; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# rsh othernode exec perl |
160
|
|
|
|
|
|
|
$proc = new_exec AnyEvent::Fork::Remote |
161
|
|
|
|
|
|
|
"/usr/bin/rsh", "rsh", "othernode", "exec perl"; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# a complicated ssh command |
164
|
|
|
|
|
|
|
$proc = new_exec AnyEvent::Fork::Remote |
165
|
|
|
|
|
|
|
"/usr/bin/ssh", |
166
|
|
|
|
|
|
|
qw(ssh -q |
167
|
|
|
|
|
|
|
-oCheckHostIP=no -oTCPKeepAlive=yes -oStrictHostKeyChecking=no |
168
|
|
|
|
|
|
|
-oGlobalKnownHostsFile=/dev/null -oUserKnownHostsFile=/dev/null |
169
|
|
|
|
|
|
|
otherhost |
170
|
|
|
|
|
|
|
exec perl); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=item my $proc = new_execp AnyEvent::Fork::Remote $file, @args... |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Just like C, except that the program is searched in the |
175
|
|
|
|
|
|
|
C<$ENV{PATH}> first, similarly to how the shell does it. This makes it easier |
176
|
|
|
|
|
|
|
to find e.g. C: |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
$proc = new_execp AnyEvent::Fork::Remote "ssh", "ssh", "otherhost", "perl"; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=item my $proc = new AnyEvent::Fork::Remote $create_callback |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Basically the same as C, but instead of a command to execute, |
183
|
|
|
|
|
|
|
it expects a callback which is invoked each time a process needs to be |
184
|
|
|
|
|
|
|
created. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
The C<$create_callback> is called with another callback as argument, |
187
|
|
|
|
|
|
|
and should call this callback with the file handle that is connected |
188
|
|
|
|
|
|
|
to a F process. This callback can be invoked even after the |
189
|
|
|
|
|
|
|
C<$create_callback> returns. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
Example: emulate C using C. |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
use AnyEvent::Util; |
194
|
|
|
|
|
|
|
use Proc::FastSpawn; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
$proc = new AnyEvent::Fork::Remote sub { |
197
|
|
|
|
|
|
|
my $done = shift; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
my ($a, $b) = AnyEvent::Util::portable_socketpair |
200
|
|
|
|
|
|
|
or die; |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
open my $oldin , "<&0" or die; |
203
|
|
|
|
|
|
|
open my $oldout, ">&1" or die; |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
open STDIN , "<&" . fileno $b or die; |
206
|
|
|
|
|
|
|
open STDOUT, ">&" . fileno $b or die; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
spawn "/usr/bin/rsh", ["rsh", "othernode", "perl"]; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
open STDIN , "<&" . fileno $oldin ; |
211
|
|
|
|
|
|
|
open STDOUT, ">&" . fileno $oldout; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
$done->($a); |
214
|
|
|
|
|
|
|
}; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=item my $proc = new_from_fh $fh |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Creates an C object from a file handle. This file |
219
|
|
|
|
|
|
|
handle must be connected to both STDIN and STDOUT of a F process. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
This form might be more convenient than C or C when |
222
|
|
|
|
|
|
|
creating an C object, but the resulting object |
223
|
|
|
|
|
|
|
does not support C. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=cut |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub new { |
228
|
1
|
|
|
1
|
1
|
2
|
my ($class, $create) = @_; |
229
|
|
|
|
|
|
|
|
230
|
1
|
|
|
|
|
9
|
bless [ |
231
|
|
|
|
|
|
|
$create, |
232
|
|
|
|
|
|
|
"", |
233
|
|
|
|
|
|
|
[], |
234
|
|
|
|
|
|
|
], $class |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub new_from_fh { |
238
|
0
|
|
|
0
|
1
|
0
|
my ($class, @fh) = @_; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
$class->new (sub { |
241
|
|
|
|
|
|
|
shift @fh |
242
|
0
|
0
|
|
0
|
|
0
|
or Carp::croak "AnyEvent::Fork::Remote::new_from_fh does not support fork"; |
243
|
0
|
|
|
|
|
0
|
}); |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub _new_exec { |
247
|
1
|
|
|
1
|
|
3
|
my $p = pop; |
248
|
|
|
|
|
|
|
|
249
|
1
|
|
|
|
|
4
|
my ($class, $program, @argv) = @_; |
250
|
|
|
|
|
|
|
|
251
|
1
|
|
|
|
|
9
|
require AnyEvent::Util; |
252
|
1
|
|
|
|
|
6
|
require Proc::FastSpawn; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
$class->new (sub { |
255
|
1
|
|
|
1
|
|
3
|
my $done = shift; |
256
|
|
|
|
|
|
|
|
257
|
1
|
50
|
|
|
|
5
|
my ($a, $b) = AnyEvent::Util::portable_socketpair () |
258
|
|
|
|
|
|
|
or die; |
259
|
|
|
|
|
|
|
|
260
|
1
|
50
|
|
|
|
89
|
open my $oldin , "<&0" or die; |
261
|
1
|
50
|
|
|
|
18
|
open my $oldout, ">&1" or die; |
262
|
|
|
|
|
|
|
|
263
|
1
|
50
|
|
|
|
23
|
open STDIN , "<&" . fileno $b or die; |
264
|
1
|
50
|
|
|
|
23
|
open STDOUT, ">&" . fileno $b or die; |
265
|
|
|
|
|
|
|
|
266
|
1
|
50
|
|
|
|
1709
|
$p ? Proc::FastSpawn::spawnp ($program, \@argv) |
267
|
|
|
|
|
|
|
: Proc::FastSpawn::spawn ($program, \@argv); |
268
|
|
|
|
|
|
|
|
269
|
1
|
|
|
|
|
27
|
open STDIN , "<&" . fileno $oldin ; |
270
|
1
|
|
|
|
|
21
|
open STDOUT, ">&" . fileno $oldout; |
271
|
|
|
|
|
|
|
|
272
|
1
|
|
|
|
|
5
|
$done->($a); |
273
|
|
|
|
|
|
|
}) |
274
|
1
|
|
|
|
|
13
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub new_exec { |
277
|
1
|
|
|
1
|
1
|
53
|
push @_, 0; |
278
|
1
|
|
|
|
|
3
|
&_new_exec |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub new_execp { |
282
|
0
|
|
|
0
|
1
|
0
|
push @_, 1; |
283
|
0
|
|
|
|
|
0
|
&_new_exec |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=item $new_proc = $proc->fork |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Quite the same as the same method of L, except that it |
289
|
|
|
|
|
|
|
simply clones the object without creating an actual process. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=cut |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub fork { |
294
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
295
|
|
|
|
|
|
|
|
296
|
0
|
|
|
|
|
0
|
bless [ |
297
|
|
|
|
|
|
|
$self->[0], |
298
|
|
|
|
|
|
|
$self->[1], |
299
|
0
|
|
|
|
|
0
|
[@{ $self->[2] }], |
300
|
|
|
|
|
|
|
], ref $self |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=item undef = $proc->pid |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
The C method always returns C and only exists for |
306
|
|
|
|
|
|
|
compatibility with L. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=cut |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub pid { |
311
|
|
|
|
|
|
|
undef |
312
|
0
|
|
|
0
|
1
|
0
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=item $proc = $proc->send_fh (...) |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
Not supported and always croaks. |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=cut |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub send_fh { |
321
|
0
|
|
|
0
|
1
|
0
|
Carp::croak "send_fh is not supported on AnyEvent::Fork::Remote objects"; |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=item $proc = $proc->eval ($perlcode, @args) |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Quite the same as the same method of L. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=cut |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# quote a binary string as a perl scalar |
331
|
|
|
|
|
|
|
sub sq($) { |
332
|
3
|
|
|
3
|
0
|
7
|
my $s = shift; |
333
|
|
|
|
|
|
|
|
334
|
3
|
50
|
|
|
|
27
|
$s =~ /'/ |
335
|
|
|
|
|
|
|
or return "'$s'"; |
336
|
|
|
|
|
|
|
|
337
|
0
|
|
|
|
|
0
|
$s =~ s/(\x10+)/\x10.'$1'.q\x10/g; |
338
|
0
|
|
|
|
|
0
|
"q\x10$s\x10" |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# quote a list of strings |
342
|
|
|
|
|
|
|
sub aq(@) { |
343
|
2
|
|
|
2
|
0
|
17
|
"(" . (join ",", map sq $_, @_) . ")" |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub eval { |
347
|
1
|
|
|
1
|
1
|
12
|
my ($self, $perlcode, @args) = @_; |
348
|
|
|
|
|
|
|
|
349
|
1
|
|
|
|
|
2
|
my $linecode = $perlcode; |
350
|
1
|
|
|
|
|
12
|
$linecode =~ s/\s+/ /g; # takes care of \n |
351
|
1
|
|
|
|
|
6
|
$linecode =~ s/"/''/g; |
352
|
1
|
50
|
|
|
|
5
|
substr $linecode, 70, length $linecode, "..." if length $linecode > 70; |
353
|
|
|
|
|
|
|
|
354
|
1
|
|
|
|
|
9
|
$self->[1] .= '{ local @_ = ' . (aq @args) . ";\n#line 1 \"'$linecode'\"\n$perlcode;\n}\n"; |
355
|
|
|
|
|
|
|
|
356
|
1
|
|
|
|
|
141
|
$self |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=item $proc = $proc->require ($module, ...) |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Quite the same as the same method of L. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=cut |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub require { |
366
|
0
|
|
|
0
|
1
|
0
|
my ($self, @modules) = @_; |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
$self->eval ("require $_") |
369
|
0
|
|
|
|
|
0
|
for @modules; |
370
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
0
|
$self |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=item $proc = $proc->send_arg ($string, ...) |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Quite the same as the same method of L. |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
=cut |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub send_arg { |
381
|
0
|
|
|
0
|
1
|
0
|
my ($self, @arg) = @_; |
382
|
|
|
|
|
|
|
|
383
|
0
|
|
|
|
|
0
|
push @{ $self->[2] }, @arg; |
|
0
|
|
|
|
|
0
|
|
384
|
|
|
|
|
|
|
|
385
|
0
|
|
|
|
|
0
|
$self |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=item $proc->run ($func, $cb->($fh)) |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
Very similar to the run method of L. |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
On the parent side, the API is identical, except that a C<$cb> argument of |
393
|
|
|
|
|
|
|
C instead of a valid file handle signals an error. |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
On the child side, the "communications socket" is in fact just C<*STDIN>, |
396
|
|
|
|
|
|
|
and typically can only be read from (this highly depends on how the |
397
|
|
|
|
|
|
|
program is created - if you just run F locally, it will work for |
398
|
|
|
|
|
|
|
both reading and writing, but commands such as F or F typically |
399
|
|
|
|
|
|
|
only provide read-only handles for STDIN). |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
To be portable, if the run function wants to read data that is written to |
402
|
|
|
|
|
|
|
C<$fh> in the parent, then it should read from STDIN. If the run function |
403
|
|
|
|
|
|
|
wants to provide data that can later be read from C<$fh>, then it should |
404
|
|
|
|
|
|
|
write them to STDOUT. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
You can write a run function that works with both L |
407
|
|
|
|
|
|
|
and this module by checking C. If it is C<0> (meaning |
408
|
|
|
|
|
|
|
it is STDIN), then you should use it for reading, and STDOUT for |
409
|
|
|
|
|
|
|
writing. Otherwise, you should use the file handle for both: |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub run { |
412
|
|
|
|
|
|
|
my ($rfh, ...) = @_; |
413
|
|
|
|
|
|
|
my $wfh = fileno $rfh ? $rfh : *STDOUT; |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# now use $rfh for reading and $wfh for writing |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=cut |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
sub run { |
421
|
1
|
|
|
1
|
1
|
5837
|
my ($self, $func, $cb) = @_; |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
$self->[0](sub { |
424
|
1
|
50
|
|
1
|
|
6
|
my $fh = shift |
425
|
|
|
|
|
|
|
or die "AnyEvent::Fork::Remote: create callback failed"; |
426
|
|
|
|
|
|
|
|
427
|
1
|
50
|
|
|
|
17
|
my $owner = length $ENV{HOSTNAME} ? "$ENV{HOSTNAME}:$$" : "*:$$"; |
428
|
|
|
|
|
|
|
|
429
|
1
|
|
|
|
|
6
|
my $code = 'BEGIN { $0 = ' . (sq "$func of $owner") . '; ' . $self->[1] . "}\n" |
430
|
|
|
|
|
|
|
. 'syswrite STDOUT, ' . (sq $magic0) . '^' . (sq $magic1) . ';' |
431
|
|
|
|
|
|
|
. '{ sysread STDIN, my $dummy, 1 }' |
432
|
1
|
|
|
|
|
7
|
. "\n$func*STDIN," . (aq @{ $self->[2] }) . ';' |
433
|
|
|
|
|
|
|
. "\n__END__\n"; |
434
|
|
|
|
|
|
|
|
435
|
1
|
|
|
|
|
7
|
AnyEvent::Util::fh_nonblocking $fh, 1; |
436
|
|
|
|
|
|
|
|
437
|
1
|
|
|
|
|
28
|
my ($rw, $ww); |
438
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
0
|
my $ofs; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
$ww = AE::io $fh, 1, sub { |
442
|
1
|
|
|
|
|
155
|
my $len = syswrite $fh, $code, 1<<20, $ofs; |
443
|
|
|
|
|
|
|
|
444
|
1
|
50
|
33
|
|
|
8
|
if ($len || $! == Errno::EAGAIN || $! == Errno::EWOULDBLOCK) { |
|
|
|
33
|
|
|
|
|
445
|
1
|
|
|
|
|
3
|
$ofs += $len; |
446
|
1
|
50
|
|
|
|
36
|
undef $ww if $ofs >= length $code; |
447
|
|
|
|
|
|
|
} else { |
448
|
|
|
|
|
|
|
# error |
449
|
0
|
|
|
|
|
0
|
($ww, $rw) = (); $cb->(undef); |
|
0
|
|
|
|
|
0
|
|
450
|
|
|
|
|
|
|
} |
451
|
1
|
|
|
|
|
23
|
}; |
452
|
|
|
|
|
|
|
|
453
|
1
|
|
|
|
|
2
|
my $rbuf; |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
$rw = AE::io $fh, 0, sub { |
456
|
1
|
|
|
|
|
3341
|
my $len = sysread $fh, $rbuf, 1<<10; |
457
|
|
|
|
|
|
|
|
458
|
1
|
50
|
33
|
|
|
9
|
if ($len || $! == Errno::EAGAIN || $! == Errno::EWOULDBLOCK) { |
|
|
|
33
|
|
|
|
|
459
|
1
|
50
|
|
|
|
5
|
$rbuf = substr $rbuf, -length $magic0 if length $rbuf > length $magic0; |
460
|
|
|
|
|
|
|
|
461
|
1
|
50
|
|
|
|
7
|
if ($rbuf eq ($magic0 ^ $magic1)) { |
462
|
|
|
|
|
|
|
# all data was sent, magic was received - both |
463
|
|
|
|
|
|
|
# directions should be "empty", and therefore |
464
|
|
|
|
|
|
|
# the socket must accept at least a single octet, |
465
|
|
|
|
|
|
|
# to signal the "child" to go on. |
466
|
1
|
|
|
|
|
2
|
undef $rw; |
467
|
1
|
50
|
|
|
|
4
|
die if $ww; # uh-oh |
468
|
|
|
|
|
|
|
|
469
|
1
|
|
|
|
|
8
|
syswrite $fh, "\n"; |
470
|
1
|
|
|
|
|
8
|
$cb->($fh); |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
} else { |
473
|
|
|
|
|
|
|
# error |
474
|
0
|
|
|
|
|
|
($ww, $rw) = (); $cb->(undef); |
|
0
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
} |
476
|
1
|
|
|
|
|
24
|
}; |
477
|
1
|
|
|
|
|
12
|
}); |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=back |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=head1 SEE ALSO |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
L, the same as this module, for local processes. |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
L, to talk to the created processes. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
L, to manage whole pools of processes. |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=head1 AUTHOR AND CONTACT INFORMATION |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
Marc Lehmann |
493
|
|
|
|
|
|
|
http://software.schmorp.de/pkg/AnyEvent-Fork-Remote |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=cut |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
1 |
498
|
|
|
|
|
|
|
|