line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#############################################################################
|
2
|
|
|
|
|
|
|
## Name: Isolate.pm
|
3
|
|
|
|
|
|
|
## Purpose: Thread::Isolate
|
4
|
|
|
|
|
|
|
## Author: Graciliano M. P.
|
5
|
|
|
|
|
|
|
## Modified by:
|
6
|
|
|
|
|
|
|
## Created: 2005-01-29
|
7
|
|
|
|
|
|
|
## RCS-ID:
|
8
|
|
|
|
|
|
|
## Copyright: (c) 2005 Graciliano M. P.
|
9
|
|
|
|
|
|
|
## Licence: This program is free software; you can redistribute it and/or
|
10
|
|
|
|
|
|
|
## modify it under the same terms as Perl itself
|
11
|
|
|
|
|
|
|
#############################################################################
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package Thread::Isolate ;
|
14
|
6
|
|
|
6
|
|
83604
|
use 5.008006 ;
|
|
6
|
|
|
|
|
23
|
|
|
6
|
|
|
|
|
276
|
|
15
|
|
|
|
|
|
|
|
16
|
6
|
|
|
6
|
|
33
|
use strict qw(vars);
|
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
204
|
|
17
|
6
|
|
|
6
|
|
31
|
no warnings ;
|
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
235
|
|
18
|
|
|
|
|
|
|
|
19
|
6
|
|
|
6
|
|
35
|
use vars qw($VERSION @ISA) ;
|
|
6
|
|
|
|
|
28
|
|
|
6
|
|
|
|
|
747
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
$VERSION = '0.05' ;
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
@ISA = qw(Thread::Isolate::Thread) ;
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub BEGIN {
|
26
|
6
|
|
|
6
|
|
35
|
*CORE::GLOBAL::exit = \&EXIT ;
|
27
|
6
|
|
|
|
|
2919
|
*CORE::GLOBAL::die = \&DIE ;
|
28
|
|
|
|
|
|
|
}
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
#######
|
31
|
|
|
|
|
|
|
# DIE #
|
32
|
|
|
|
|
|
|
#######
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub DIE {
|
35
|
6
|
|
|
6
|
|
55687
|
my $is_exit ;
|
36
|
6
|
50
|
|
|
|
43
|
if ( $_[0] =~ /#CORE::GLOBAL::exit#/s ) {
|
37
|
0
|
|
|
|
|
0
|
my $err = shift ;
|
38
|
0
|
|
|
|
|
0
|
$err =~ s/#CORE::GLOBAL::exit#/exit()/gsi ; ;
|
39
|
0
|
|
|
|
|
0
|
unshift (@_, $err) ;
|
40
|
0
|
|
|
|
|
0
|
$is_exit = 1 ;
|
41
|
|
|
|
|
|
|
}
|
42
|
|
|
|
|
|
|
|
43
|
6
|
50
|
|
|
|
39
|
if ( $^S ) {
|
44
|
6
|
|
|
|
|
24921
|
my $thi = Thread::Isolate->self ;
|
45
|
0
|
0
|
|
|
|
|
$thi->add_job('SHUTDOWN') if $thi ;
|
46
|
0
|
|
|
|
|
|
CORE::die(@_) ;
|
47
|
|
|
|
|
|
|
}
|
48
|
|
|
|
|
|
|
else {
|
49
|
0
|
0
|
|
|
|
|
if ( $is_exit ) {
|
50
|
0
|
0
|
|
|
|
|
Thread::Isolate->new_from_id( $Thread::Isolate::Thread::MOTHER_THREAD )->eval(' CORE::exit() ;') if $Thread::Isolate::Thread::MOTHER_THREAD ;
|
51
|
0
|
|
|
|
|
|
CORE::exit ;
|
52
|
|
|
|
|
|
|
}
|
53
|
0
|
|
|
|
|
|
else { warn(@_) ;}
|
54
|
|
|
|
|
|
|
}
|
55
|
|
|
|
|
|
|
}
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
########
|
58
|
|
|
|
|
|
|
# EXIT #
|
59
|
|
|
|
|
|
|
########
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub EXIT {
|
62
|
0
|
|
|
0
|
|
|
my @call = caller ;
|
63
|
0
|
0
|
|
|
|
|
if ( $call[1] =~ /^\(eval/ ) {
|
64
|
0
|
|
|
|
|
|
my @call2 = caller(1) ;
|
65
|
0
|
|
|
|
|
|
die("#CORE::GLOBAL::exit# at $call[1] (package $call[0]) line $call[2]:\n$call2[6]\n") ;
|
66
|
|
|
|
|
|
|
}
|
67
|
|
|
|
|
|
|
else {
|
68
|
0
|
|
|
|
|
|
die("#CORE::GLOBAL::exit# at $call[1] (package $call[0]) line $call[2].\n") ;
|
69
|
|
|
|
|
|
|
}
|
70
|
|
|
|
|
|
|
}
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
###########
|
73
|
|
|
|
|
|
|
# REQUIRE #
|
74
|
|
|
|
|
|
|
###########
|
75
|
|
|
|
|
|
|
|
76
|
6
|
|
|
6
|
|
9765
|
use Storable () ;
|
|
6
|
|
|
|
|
34500
|
|
|
6
|
|
|
|
|
448
|
|
77
|
6
|
|
|
6
|
|
6615
|
use Thread::Isolate::Thread ;
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
Thread::Isolate::Thread::start_mother_thread() ;
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
######################
|
82
|
|
|
|
|
|
|
# STORABLE SIGNATURE #
|
83
|
|
|
|
|
|
|
######################
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
use vars qw($STORABLE_SIGN $USE_EXTERNAL_PERL) ;
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
BEGIN {
|
88
|
|
|
|
|
|
|
return if $STORABLE_SIGN ;
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
($USE_EXTERNAL_PERL , $STORABLE_SIGN) = ('','') ;
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
if ( $STORABLE_SIGN eq '' ) {
|
93
|
|
|
|
|
|
|
if (!$USE_EXTERNAL_PERL) {
|
94
|
|
|
|
|
|
|
$STORABLE_SIGN = unpack( 'l',Storable::freeze( [] )) ;
|
95
|
|
|
|
|
|
|
}
|
96
|
|
|
|
|
|
|
else {
|
97
|
|
|
|
|
|
|
open( my $handle,
|
98
|
|
|
|
|
|
|
qq($^X -MStorable -e "print unpack('l',Storable::freeze( [] ))" | )
|
99
|
|
|
|
|
|
|
) or die "Cannot determine Storable signature\n" ;
|
100
|
|
|
|
|
|
|
$STORABLE_SIGN = <$handle>;
|
101
|
|
|
|
|
|
|
$USE_EXTERNAL_PERL = 'Signature obtained with an external Perl!' ;
|
102
|
|
|
|
|
|
|
}
|
103
|
|
|
|
|
|
|
}
|
104
|
|
|
|
|
|
|
}
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
##########
|
107
|
|
|
|
|
|
|
# FREEZE #
|
108
|
|
|
|
|
|
|
##########
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub freeze {
|
111
|
|
|
|
|
|
|
if (@_) {
|
112
|
|
|
|
|
|
|
foreach (@_) {
|
113
|
|
|
|
|
|
|
if ( !defined() or ref() or m#\0# ) {
|
114
|
|
|
|
|
|
|
my ( $stable_tree , $holder ) = make_stable_tree(\@_) ;
|
115
|
|
|
|
|
|
|
my $freeze = Storable::freeze($stable_tree) ;
|
116
|
|
|
|
|
|
|
make_stable_tree($stable_tree , $holder , 1) ;
|
117
|
|
|
|
|
|
|
return $freeze ;
|
118
|
|
|
|
|
|
|
}
|
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
return join("\0" , @_) ;
|
121
|
|
|
|
|
|
|
}
|
122
|
|
|
|
|
|
|
else { return ;}
|
123
|
|
|
|
|
|
|
}
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
########
|
126
|
|
|
|
|
|
|
# THAW #
|
127
|
|
|
|
|
|
|
########
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub thaw {
|
130
|
|
|
|
|
|
|
return unless defined( $_[0] ) and defined( wantarray ) ;
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
if ( (unpack('l', $_[0]) || 0) == $STORABLE_SIGN ) {
|
133
|
|
|
|
|
|
|
my $thaw = Storable::thaw( $_[0] ) ;
|
134
|
|
|
|
|
|
|
restore_stable_tree($thaw) ;
|
135
|
|
|
|
|
|
|
return wantarray ? @$thaw : $$thaw[0] ;
|
136
|
|
|
|
|
|
|
}
|
137
|
|
|
|
|
|
|
else {
|
138
|
|
|
|
|
|
|
if (wantarray) {
|
139
|
|
|
|
|
|
|
return split("\0" , $_[0]) ;
|
140
|
|
|
|
|
|
|
}
|
141
|
|
|
|
|
|
|
else {
|
142
|
|
|
|
|
|
|
return $1 if $_[0] =~ m#^([^\0]*)# ;
|
143
|
|
|
|
|
|
|
return $_[0] ;
|
144
|
|
|
|
|
|
|
}
|
145
|
|
|
|
|
|
|
}
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
}
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
####################
|
150
|
|
|
|
|
|
|
# MAKE_STABLE_TREE #
|
151
|
|
|
|
|
|
|
####################
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub make_stable_tree {
|
154
|
|
|
|
|
|
|
my $ref = shift ;
|
155
|
|
|
|
|
|
|
my $holder = shift(@_) || [] ;
|
156
|
|
|
|
|
|
|
my $restore = shift ;
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
if ( !ref $ref ) {
|
159
|
|
|
|
|
|
|
return wantarray ? ( $ref , $holder ) : $ref ;
|
160
|
|
|
|
|
|
|
}
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
if (ref $ref eq 'GLOB') {
|
163
|
|
|
|
|
|
|
push(@$holder , $ref) ;
|
164
|
|
|
|
|
|
|
my $fileno = fileno($ref) || '' . *$ref ;
|
165
|
|
|
|
|
|
|
$ref = bless(['GLOB' , $fileno] , 'Thread::Isolate::FREEZE') ;
|
166
|
|
|
|
|
|
|
}
|
167
|
|
|
|
|
|
|
elsif (ref $ref eq 'CODE') {
|
168
|
|
|
|
|
|
|
push(@$holder , $ref) ;
|
169
|
|
|
|
|
|
|
$ref = bless(['CODE' , undef] , 'Thread::Isolate::FREEZE') ;
|
170
|
|
|
|
|
|
|
}
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
if (ref $ref eq 'HASH') {
|
173
|
|
|
|
|
|
|
foreach my $Key ( sort keys %$ref ) {
|
174
|
|
|
|
|
|
|
&make_stable_tree($$ref{$Key} , $holder , $restore) if ref $$ref{$Key} ;
|
175
|
|
|
|
|
|
|
}
|
176
|
|
|
|
|
|
|
}
|
177
|
|
|
|
|
|
|
elsif (ref $ref eq 'ARRAY') {
|
178
|
|
|
|
|
|
|
foreach my $i ( @$ref ) {
|
179
|
|
|
|
|
|
|
$i = &make_stable_tree($i , $holder , $restore) if ref $i ;
|
180
|
|
|
|
|
|
|
}
|
181
|
|
|
|
|
|
|
}
|
182
|
|
|
|
|
|
|
elsif (ref $ref eq 'SCALAR' || ref $ref eq 'REF') {
|
183
|
|
|
|
|
|
|
$$ref = &make_stable_tree($$ref , $holder , $restore) if ref $$ref ;
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
elsif (ref $ref eq 'Thread::Isolate::FREEZE') {
|
186
|
|
|
|
|
|
|
if ( $restore == 1 ) {
|
187
|
|
|
|
|
|
|
$ref = shift @$holder ;
|
188
|
|
|
|
|
|
|
}
|
189
|
|
|
|
|
|
|
elsif ( $restore == 2 ) {
|
190
|
|
|
|
|
|
|
if ( $$ref[0] eq 'GLOB' ) {
|
191
|
|
|
|
|
|
|
if ( $$ref[1] =~ /^\d+$/ ) {
|
192
|
|
|
|
|
|
|
open(my $fh , "+<&=$$ref[1]") ;
|
193
|
|
|
|
|
|
|
$ref = $fh ;
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
elsif ( $$ref[1] =~ /^\*(.+)/s ) {
|
196
|
|
|
|
|
|
|
$ref = \*{$1} ;
|
197
|
|
|
|
|
|
|
}
|
198
|
|
|
|
|
|
|
}
|
199
|
|
|
|
|
|
|
elsif ( $$ref[0] eq 'CODE' ) {
|
200
|
|
|
|
|
|
|
$ref = eval('sub {}') ;
|
201
|
|
|
|
|
|
|
}
|
202
|
|
|
|
|
|
|
}
|
203
|
|
|
|
|
|
|
}
|
204
|
|
|
|
|
|
|
elsif (ref $ref && UNIVERSAL::isa($ref , 'UNIVERSAL')) {
|
205
|
|
|
|
|
|
|
if ( UNIVERSAL::isa($ref , 'HASH') ) {
|
206
|
|
|
|
|
|
|
foreach my $Key ( sort keys %$ref ) {
|
207
|
|
|
|
|
|
|
$$ref{$Key} = &make_stable_tree($$ref{$Key} , $holder , $restore) if ref $$ref{$Key} ;
|
208
|
|
|
|
|
|
|
}
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($ref , 'ARRAY') ) {
|
211
|
|
|
|
|
|
|
foreach my $i ( @$ref ) {
|
212
|
|
|
|
|
|
|
$i = &make_stable_tree($i , $holder , $restore) if ref $i ;
|
213
|
|
|
|
|
|
|
}
|
214
|
|
|
|
|
|
|
}
|
215
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($ref , 'SCALAR') || UNIVERSAL::isa($ref , 'REF') ) {
|
216
|
|
|
|
|
|
|
$$ref = &make_stable_tree($$ref , $holder , $restore) if ref $$ref ;
|
217
|
|
|
|
|
|
|
}
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
return wantarray ? ( $ref , $holder ) : $ref ;
|
221
|
|
|
|
|
|
|
}
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
#######################
|
224
|
|
|
|
|
|
|
# RESTORE_STABLE_TREE #
|
225
|
|
|
|
|
|
|
#######################
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub restore_stable_tree {
|
228
|
|
|
|
|
|
|
my $stable_tree = shift ;
|
229
|
|
|
|
|
|
|
return make_stable_tree($stable_tree , undef , 2) ;
|
230
|
|
|
|
|
|
|
}
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
#######
|
233
|
|
|
|
|
|
|
# END #
|
234
|
|
|
|
|
|
|
#######
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
1;
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
__END__
|