line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Parallel::PreForkManager; |
2
|
|
|
|
|
|
|
|
3
|
16
|
|
|
16
|
|
25155
|
use strict; |
|
16
|
|
|
|
|
16
|
|
|
16
|
|
|
|
|
348
|
|
4
|
16
|
|
|
16
|
|
61
|
use warnings; |
|
16
|
|
|
|
|
16
|
|
|
16
|
|
|
|
|
492
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '1.20170415'; # VERSION |
7
|
|
|
|
|
|
|
|
8
|
16
|
|
|
16
|
|
49
|
use Carp; |
|
16
|
|
|
|
|
20
|
|
|
16
|
|
|
|
|
785
|
|
9
|
16
|
|
|
16
|
|
7351
|
use IO::Handle; |
|
16
|
|
|
|
|
71060
|
|
|
16
|
|
|
|
|
595
|
|
10
|
16
|
|
|
16
|
|
6693
|
use IO::Select; |
|
16
|
|
|
|
|
17647
|
|
|
16
|
|
|
|
|
615
|
|
11
|
16
|
|
|
16
|
|
7817
|
use JSON; |
|
16
|
|
|
|
|
151516
|
|
|
16
|
|
|
|
|
68
|
|
12
|
16
|
|
|
16
|
|
9097
|
use English qw( -no_match_vars ); |
|
16
|
|
|
|
|
43817
|
|
|
16
|
|
|
|
|
81
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my $DEBUG = 0; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub new { |
17
|
11
|
|
|
11
|
1
|
1760
|
my ( $Class, $Args ) = @_; |
18
|
|
|
|
|
|
|
|
19
|
11
|
50
|
|
|
|
44
|
croak "No ChildHandler set" if ! exists ( $Args->{'ChildHandler'} ); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my $Self = { |
22
|
|
|
|
|
|
|
'ChildHandler' => $Args->{'ChildHandler'}, |
23
|
|
|
|
|
|
|
'ChildCount' => $Args->{'ChildCount'} || 10, |
24
|
|
|
|
|
|
|
'Timeout' => $Args->{'Timeout'} || 0, |
25
|
11
|
|
50
|
|
|
198
|
'WaitComplete' => $Args->{'WaitComplete'} || 1, |
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
26
|
|
|
|
|
|
|
'JobQueue' => [], |
27
|
|
|
|
|
|
|
'Select' => IO::Select->new(), |
28
|
|
|
|
|
|
|
}; |
29
|
|
|
|
|
|
|
|
30
|
11
|
|
|
|
|
121
|
foreach my $Arg ( qw { ParentCallback ProgressCallback JobsPerChild ChildSetupHook ChildTeardownHook } ) { |
31
|
55
|
100
|
|
|
|
132
|
$Self->{ $Arg } = $Args->{ $Arg } if exists ( $Args->{ $Arg } ); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
11
|
|
33
|
|
|
66
|
bless $Self, ref($Class) || $Class; |
35
|
|
|
|
|
|
|
|
36
|
11
|
|
|
|
|
22
|
return $Self; |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub AddJob { |
40
|
220
|
|
|
220
|
1
|
385
|
my ( $Self, $Job ) = @_; |
41
|
220
|
|
|
|
|
220
|
push @{ $Self->{'JobQueue'} }, $Job; |
|
220
|
|
|
|
|
209
|
|
42
|
220
|
|
|
|
|
187
|
return; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub RunJobs { |
46
|
11
|
|
|
11
|
1
|
44
|
my ($Self) = @_; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# If a worker dies, there's a problem |
49
|
|
|
|
|
|
|
local $SIG{CHLD} = sub { |
50
|
7
|
|
|
7
|
|
91653
|
my $pid = wait(); |
51
|
7
|
50
|
|
|
|
39975
|
if ( exists ( $Self->{'ToChild'}->{$pid} ) ) { |
52
|
0
|
|
|
|
|
0
|
confess("Worker $pid died."); |
53
|
|
|
|
|
|
|
} |
54
|
11
|
|
|
|
|
253
|
}; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Start the workers |
57
|
11
|
|
|
|
|
44
|
$Self->StartChildren(); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Read from the workers, loop until they all shut down |
60
|
9
|
|
|
|
|
90
|
while ( %{ $Self->{'ToChild'} } ) { |
|
10
|
|
|
|
|
662
|
|
61
|
|
|
|
|
|
|
READYLOOP: |
62
|
9
|
|
|
|
|
72
|
while ( my @Ready = $Self->{'Select'}->can_read() ) { |
63
|
|
|
|
|
|
|
READLOOP: |
64
|
241
|
|
|
|
|
27738
|
foreach my $fh (@Ready) { |
65
|
246
|
|
|
|
|
799
|
my $Result = $Self->Receive($fh); |
66
|
|
|
|
|
|
|
|
67
|
246
|
50
|
|
|
|
422
|
if ( !$Result ) { |
68
|
0
|
|
|
|
|
0
|
$Self->{'Select'}->remove($fh); |
69
|
0
|
|
|
|
|
0
|
print STDERR "$fh got eof\n"; |
70
|
0
|
|
|
|
|
0
|
next READLOOP; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
246
|
|
|
|
|
517
|
my $ResultMethod = $Result->{ 'Method' }; |
74
|
246
|
50
|
|
|
|
500
|
warn "Parent working on Method $ResultMethod\n" if $DEBUG; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# Handle the initial request for work |
77
|
246
|
100
|
|
|
|
600
|
if ( $ResultMethod eq 'Startup' ) { |
78
|
50
|
50
|
|
|
|
87
|
if ( $#{ $Self->{'JobQueue'} } > -1 ) { |
|
50
|
|
|
|
|
149
|
|
79
|
|
|
|
|
|
|
#my $Child = $Self->{ 'ToChild' }->{ $Result->{ 'pid' } }; |
80
|
50
|
|
|
|
|
44
|
my $NextJob = shift( @{ $Self->{'JobQueue'} } ); |
|
50
|
|
|
|
|
97
|
|
81
|
50
|
|
|
|
|
278
|
$Self->Send( $Self->{'ToChild'}->{ $Result->{'pid'} }, { 'Job' => $NextJob, }, ); |
82
|
50
|
|
|
|
|
532
|
next READLOOP; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
else { |
85
|
|
|
|
|
|
|
# Nothing to do, shut down |
86
|
0
|
|
|
|
|
0
|
$Self->{'Select'}->remove($fh); |
87
|
0
|
|
|
|
|
0
|
my $fh = $Self->{'ToChild'}->{ $Result->{'pid'} }; |
88
|
0
|
|
|
|
|
0
|
delete( $Self->{'ToChild'}->{ $Result->{'pid'} } ); |
89
|
0
|
|
|
|
|
0
|
$Self->Send( $fh, { 'Shutdown' => 1, }, ); |
90
|
0
|
|
|
|
|
0
|
close($fh); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Process the result handler |
95
|
196
|
100
|
|
|
|
638
|
if ( $ResultMethod eq 'Completed' ) { |
96
|
|
|
|
|
|
|
# The child has completed it's work, process the results. |
97
|
96
|
50
|
33
|
|
|
885
|
if ( $Result->{'Data'} && exists( $Self->{'ParentCallback'} ) ) { |
98
|
96
|
|
|
|
|
154
|
&{ $Self->{'ParentCallback'} }( $Self, $Result->{'Data'} ); |
|
96
|
|
|
|
|
344
|
|
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# If the child has reached its processing limit then shut it down |
102
|
96
|
100
|
|
|
|
1061
|
if ( exists( $Result->{'JobsPerChildLimitReached'} ) ) { |
103
|
46
|
|
|
|
|
149
|
$Self->{'Select'}->remove($fh); |
104
|
46
|
|
|
|
|
1322
|
my $fh = $Self->{'ToChild'}->{ $Result->{'pid'} }; |
105
|
46
|
|
|
|
|
124
|
delete( $Self->{'ToChild'}->{ $Result->{'pid'} } ); |
106
|
46
|
|
|
|
|
641
|
$Self->Send( $fh, { 'Shutdown' => 1, }, ); |
107
|
46
|
|
|
|
|
272
|
close($fh); |
108
|
|
|
|
|
|
|
# If there are still jobs to be done then start a new child |
109
|
46
|
100
|
|
|
|
47
|
if ( $#{ $Self->{'JobQueue'} } > -1 ) { |
|
46
|
|
|
|
|
174
|
|
110
|
44
|
|
|
|
|
100
|
$Self->StartChild(); |
111
|
|
|
|
|
|
|
} |
112
|
38
|
|
|
|
|
2616
|
next READLOOP; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# If there's still work to be done, send it to the child |
116
|
50
|
50
|
|
|
|
37
|
if ( $#{ $Self->{'JobQueue'} } > -1 ) { |
|
50
|
|
|
|
|
156
|
|
117
|
50
|
|
|
|
|
39
|
my $NextJob = shift( @{ $Self->{'JobQueue'} } ); |
|
50
|
|
|
|
|
146
|
|
118
|
50
|
|
|
|
|
178
|
$Self->Send( $Self->{'ToChild'}->{ $Result->{'pid'} }, { 'Job' => $NextJob, }, ); |
119
|
50
|
|
|
|
|
406
|
next READLOOP; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# There is no more work to be done, shut down this child |
123
|
0
|
|
|
|
|
0
|
$Self->{'Select'}->remove($fh); |
124
|
0
|
|
|
|
|
0
|
my $fh = $Self->{'ToChild'}->{ $Result->{pid} }; |
125
|
0
|
|
|
|
|
0
|
delete( $Self->{'ToChild'}->{ $Result->{pid} } ); |
126
|
0
|
|
|
|
|
0
|
close($fh); |
127
|
0
|
|
|
|
|
0
|
next READLOOP; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
100
|
50
|
|
|
|
2728
|
if ( $ResultMethod eq 'ProgressCallback' ) { |
131
|
100
|
|
|
|
|
371
|
my $Method = $Result->{'ProgressCallbackMethod'}; |
132
|
100
|
|
|
|
|
409
|
my $Data = $Result->{'ProgressCallbackData'}; |
133
|
100
|
50
|
|
|
|
427
|
if ( exists( $Self->{'ProgressCallback'}->{$Method} ) ) { |
134
|
100
|
|
|
|
|
157
|
my $MethodResult = &{ $Self->{'ProgressCallback'}->{$Method} }( $Self, $Data ); |
|
100
|
|
|
|
|
460
|
|
135
|
100
|
|
|
|
|
1563
|
$Self->Send( $Self->{'ToChild'}->{ $Result->{'pid'} }, $MethodResult ); |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
else { |
139
|
0
|
|
|
|
|
0
|
confess "Unknown callback method"; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
100
|
|
|
|
|
628
|
next READLOOP; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
1
|
50
|
|
|
|
16
|
if ( $Self->{ 'WaitComplete' } ) { |
150
|
1
|
|
|
|
|
7
|
$Self->WaitComplete(); |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
1
|
|
|
|
|
22
|
return; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub WaitComplete { |
157
|
1
|
|
|
1
|
1
|
3
|
my ( $Self ) = @_; |
158
|
1
|
|
|
|
|
139361
|
while ( ( my $pid = wait() ) != -1 ) { } |
159
|
1
|
|
|
|
|
4
|
return; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub StartChildren { |
163
|
11
|
|
|
11
|
1
|
22
|
my ($Self) = @_; |
164
|
|
|
|
|
|
|
|
165
|
11
|
|
|
|
|
11
|
my $MaxChildren = $Self->{ 'ChildCount' }; |
166
|
11
|
|
|
|
|
22
|
my $ActualJobs = scalar @{ $Self->{ 'JobQueue' } }; |
|
11
|
|
|
|
|
11
|
|
167
|
|
|
|
|
|
|
|
168
|
11
|
50
|
|
|
|
33
|
if ( $ActualJobs < $MaxChildren ) { |
169
|
0
|
|
|
|
|
0
|
$MaxChildren = $ActualJobs; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
11
|
|
|
|
|
33
|
foreach ( 1 .. $MaxChildren ) { |
173
|
21
|
|
|
|
|
53
|
$Self->StartChild(); |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
9
|
|
|
|
|
45
|
return; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub StartChild { |
180
|
65
|
|
|
65
|
1
|
85
|
my ($Self) = @_; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# Open a pipe for the worker |
183
|
65
|
|
|
|
|
55
|
my ( $FromParent, $FromChild, $ToParent, $ToChild ); |
184
|
65
|
|
|
|
|
1541
|
pipe( $FromParent, $ToChild ); |
185
|
65
|
|
|
|
|
695
|
pipe( $FromChild, $ToParent ); |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# Fork off a worker |
188
|
65
|
|
|
|
|
34550
|
my $pid = fork(); |
189
|
|
|
|
|
|
|
|
190
|
65
|
100
|
|
|
|
1845
|
if ($pid) { |
|
|
50
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# Parent |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Close unused pipes |
194
|
55
|
|
|
|
|
1083
|
close($ToParent); |
195
|
55
|
|
|
|
|
514
|
close($FromParent); |
196
|
|
|
|
|
|
|
|
197
|
55
|
|
|
|
|
1210
|
$Self->{'ToChild'}->{$pid} = $ToChild; |
198
|
55
|
|
|
|
|
436
|
$Self->{'FromChild'}->{$pid} = $FromChild; |
199
|
55
|
|
|
|
|
1872
|
$Self->{'Select'}->add($FromChild); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
elsif ( $pid == 0 ) { |
203
|
|
|
|
|
|
|
# Child |
204
|
|
|
|
|
|
|
|
205
|
10
|
50
|
|
|
|
290
|
warn "Child $PID spawned" if $DEBUG; |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# Close unused pipes |
208
|
10
|
|
|
|
|
347
|
close($FromChild); |
209
|
10
|
|
|
|
|
248
|
close($ToChild); |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# Setup communication pipes |
212
|
10
|
|
|
|
|
163
|
$Self->{'ToParent'} = $ToParent; |
213
|
10
|
|
|
|
|
857
|
open( STDIN, '<', '/dev/null' ); |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# Send the initial request |
216
|
10
|
|
|
|
|
339
|
$Self->Send( $ToParent, { 'Method' => 'Startup' } ); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# Start processing |
219
|
10
|
|
|
|
|
88
|
$Self->Child($FromParent); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# When the worker subroutine completes, exit |
222
|
0
|
|
|
|
|
0
|
exit 0; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
else { |
225
|
0
|
|
|
|
|
0
|
confess("Failed to fork: $!"); |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
55
|
|
|
|
|
6806
|
return; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub Child { |
232
|
10
|
|
|
10
|
1
|
23
|
my ( $Self, $FromParent ) = @_; |
233
|
10
|
|
|
|
|
64
|
$Self->{'FromParent'} = $FromParent; |
234
|
|
|
|
|
|
|
|
235
|
10
|
50
|
|
|
|
57
|
if ( exists( $Self->{'ChildSetupHook'} ) ) { |
236
|
0
|
|
|
|
|
0
|
&{ $Self->{'ChildSetupHook'} }( $Self ); |
|
0
|
|
|
|
|
0
|
|
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Read instructions from the parent |
240
|
10
|
|
|
|
|
643
|
while ( my $Instructions = $Self->Receive($FromParent) ) { |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# If the handler's children die, that's not our business |
243
|
30
|
|
|
|
|
370
|
$SIG{CHLD} = 'IGNORE'; |
244
|
|
|
|
|
|
|
|
245
|
30
|
100
|
|
|
|
352
|
if ( exists( $Instructions->{'Shutdown'} ) ) { |
246
|
10
|
50
|
|
|
|
65
|
warn "Child $PID shutdown" if $DEBUG; |
247
|
10
|
50
|
|
|
|
59
|
if ( exists( $Self->{'ChildTeardownHook'} ) ) { |
248
|
0
|
|
|
|
|
0
|
&{ $Self->{'ChildTeardownHook'} }( $Self ); |
|
0
|
|
|
|
|
0
|
|
249
|
|
|
|
|
|
|
} |
250
|
10
|
|
|
|
|
3187
|
exit 0; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# Execute the handler with the given instructions |
254
|
20
|
|
|
|
|
37
|
my $Result; |
255
|
20
|
|
|
|
|
60
|
eval { |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Handle alarms |
258
|
|
|
|
|
|
|
local $SIG{ALRM} = sub { |
259
|
0
|
|
|
0
|
|
0
|
die "Child timed out."; |
260
|
20
|
|
|
|
|
422
|
}; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# Set alarm |
263
|
20
|
|
|
|
|
125
|
alarm( $Self->{'Timeout'} ); |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Execute the handler and get it's result |
266
|
20
|
50
|
|
|
|
137
|
if ( exists( $Self->{'ChildHandler'} ) ) { |
267
|
20
|
|
|
|
|
57
|
$Result = &{ $Self->{'ChildHandler'} }( $Self, $Instructions->{'Job'} ); |
|
20
|
|
|
|
|
197
|
|
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# Disable alarm |
271
|
20
|
|
|
|
|
287
|
alarm(0); |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
}; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# Warn on errors |
276
|
20
|
50
|
|
|
|
52
|
if ($@) { |
277
|
0
|
0
|
|
|
|
0
|
if ( exists( $Self->{'ChildTeardownHook'} ) ) { |
278
|
0
|
|
|
|
|
0
|
&{ $Self->{'ChildTeardownHook'} }( $Self ); |
|
0
|
|
|
|
|
0
|
|
279
|
|
|
|
|
|
|
} |
280
|
0
|
|
|
|
|
0
|
croak("Child $PID error: $@"); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
20
|
|
|
|
|
181
|
my $ResultToParent = { |
284
|
|
|
|
|
|
|
'Method' => 'Completed', |
285
|
|
|
|
|
|
|
'Data' => $Result, |
286
|
|
|
|
|
|
|
}; |
287
|
|
|
|
|
|
|
|
288
|
20
|
50
|
|
|
|
65
|
if ( exists( $Self->{'JobsPerChild'} ) ) { |
289
|
20
|
|
|
|
|
69
|
$Self->{'JobsPerChild'} = $Self->{'JobsPerChild'} - 1; |
290
|
20
|
100
|
|
|
|
94
|
if ( $Self->{'JobsPerChild'} == 0 ) { |
291
|
10
|
|
|
|
|
58
|
$ResultToParent->{'JobsPerChildLimitReached'} = 1; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# Send the result to the server |
296
|
20
|
|
|
|
|
67
|
$Self->Send( $Self->{'ToParent'}, $ResultToParent ); |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
0
|
0
|
|
|
|
0
|
if ( exists( $Self->{'ChildTeardownHook'} ) ) { |
300
|
0
|
|
|
|
|
0
|
&{ $Self->{'ChildTeardownHook'} }( $Self ); |
|
0
|
|
|
|
|
0
|
|
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
0
|
0
|
|
|
|
0
|
warn "Child $PID completed" if $DEBUG; |
304
|
0
|
|
|
|
|
0
|
exit 0; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
sub ProgressCallback { |
308
|
20
|
|
|
20
|
1
|
348
|
my ( $Self, $Method, $Data ) = @_; |
309
|
20
|
|
|
|
|
220
|
$Self->Send( $Self->{'ToParent'}, { |
310
|
|
|
|
|
|
|
'Method' => 'ProgressCallback', |
311
|
|
|
|
|
|
|
'ProgressCallbackMethod' => $Method, |
312
|
|
|
|
|
|
|
'ProgressCallbackData' => $Data, |
313
|
|
|
|
|
|
|
} ); |
314
|
20
|
|
|
|
|
88
|
my $Result = $Self->Receive( $Self->{'FromParent'} ); |
315
|
20
|
|
|
|
|
73
|
return $Result; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub Receive { |
319
|
296
|
|
|
296
|
1
|
290
|
my ( $Self, $fh ) = @_; |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Get a value from the file handle |
322
|
296
|
|
|
|
|
249
|
my $Value; |
323
|
|
|
|
|
|
|
my $Char; |
324
|
296
|
|
|
|
|
69910
|
while ( read( $fh, $Char, 1 ) ) { |
325
|
22782
|
100
|
|
|
|
34050
|
if ( $Char eq "\n" ) { |
326
|
296
|
|
|
|
|
405
|
last; |
327
|
|
|
|
|
|
|
} |
328
|
22486
|
|
|
|
|
47679
|
$Value .= $Char; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# Deserialize the data |
332
|
296
|
|
|
|
|
548
|
my $Data = eval { decode_json($Value) }; |
|
296
|
|
|
|
|
3339
|
|
333
|
|
|
|
|
|
|
|
334
|
296
|
|
|
|
|
734
|
return $Data; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
sub Send { |
338
|
296
|
|
|
296
|
1
|
514
|
my ( $Self, $fh, $Value ) = @_; |
339
|
|
|
|
|
|
|
|
340
|
296
|
|
|
|
|
880
|
$Value->{'pid'} = $PID; |
341
|
|
|
|
|
|
|
|
342
|
296
|
|
|
|
|
1761
|
my $Encoded = encode_json($Value); |
343
|
296
|
|
|
|
|
1443
|
print $fh "$Encoded\n"; |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# Force the file handle to flush |
346
|
296
|
|
|
|
|
6870
|
$fh->flush(); |
347
|
|
|
|
|
|
|
|
348
|
296
|
|
|
|
|
675
|
return; |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
1; |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
__END__ |