line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Pcore::Core::Exception; |
2
|
|
|
|
|
|
|
|
3
|
5
|
|
|
|
|
48
|
use Pcore -export => { # |
4
|
|
|
|
|
|
|
DEFAULT => [qw[croak cluck]], |
5
|
5
|
|
|
5
|
|
36
|
}; |
|
5
|
|
|
|
|
13
|
|
6
|
5
|
|
|
5
|
|
36
|
use Carp qw[]; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
108
|
|
7
|
5
|
|
|
5
|
|
1557
|
use Pcore::Core::Exception::Object; |
|
5
|
|
|
|
|
21
|
|
|
5
|
|
|
|
|
932
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $IGNORE_ERRORS = 1; # do not write errors to error log channel by default |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# needed to properly destruct TEMP_DIR |
12
|
|
|
|
|
|
|
$SIG->{INT} = AE::signal INT => \&SIGINT; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# required for properly remove TEMP_DIR |
15
|
|
|
|
|
|
|
$SIG->{TERM} = AE::signal TERM => \&SIGTERM; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
$SIG{__DIE__} = \&SIGDIE; ## no critic qw[Variables::RequireLocalizedPunctuationVars] |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
$SIG{__WARN__} = \&SIGWARN; ## no critic qw[Variables::RequireLocalizedPunctuationVars] |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# we don't need stacktrace from Error::TypeTiny exceptions |
22
|
|
|
|
|
|
|
$Error::TypeTiny::StackTrace = 0; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# redefine Carp::longmess, Carp::shotmess, disable stack trace |
25
|
|
|
|
|
|
|
{ |
26
|
5
|
|
|
5
|
|
47
|
no warnings qw[redefine]; |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
7968
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
*Carp::longmess = *Carp::shortmess = sub { |
29
|
0
|
0
|
|
0
|
|
0
|
if ( defined $_[0] ) { |
30
|
0
|
|
|
|
|
0
|
return $_[0]; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
else { |
33
|
0
|
|
|
|
|
0
|
return q[]; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
}; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub SIGINT { |
39
|
0
|
|
|
0
|
0
|
0
|
exit 128 + 2; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub SIGTERM { |
43
|
0
|
|
|
0
|
0
|
0
|
exit 128 + 15; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# SIGNALS |
47
|
|
|
|
|
|
|
sub SIGDIE { |
48
|
9
|
|
|
9
|
1
|
2729
|
my $e = Pcore::Core::Exception::Object->new( $_[0], level => 'ERROR', skip_frames => 1, with_trace => 1 ); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# error in AE callback |
51
|
9
|
50
|
33
|
|
|
440
|
if ( $^S && $e->{is_ae_cb_error} ) { |
|
|
50
|
33
|
|
|
|
|
52
|
|
|
|
|
|
|
{ |
53
|
0
|
|
|
|
|
0
|
local $@; |
|
0
|
|
|
|
|
0
|
|
54
|
|
|
|
|
|
|
|
55
|
0
|
|
|
|
|
0
|
eval { $e->sendlog('FATAL') }; |
|
0
|
|
|
|
|
0
|
|
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
0
|
|
|
|
|
0
|
return CORE::die $e; # set $@ to $e |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# ERROR, !defined $^S - parsing module, eval, or main program, true - executing an eval |
62
|
|
|
|
|
|
|
elsif ( !defined $^S || $^S ) { |
63
|
9
|
50
|
|
|
|
42
|
if ( !$IGNORE_ERRORS ) { |
64
|
0
|
|
|
|
|
0
|
local $@; |
65
|
|
|
|
|
|
|
|
66
|
0
|
|
|
|
|
0
|
eval { $e->sendlog('ERROR') }; |
|
0
|
|
|
|
|
0
|
|
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
9
|
|
|
|
|
85
|
return CORE::die $e; # set $@ to $e |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# FATAL |
73
|
|
|
|
|
|
|
else { |
74
|
|
|
|
|
|
|
{ |
75
|
0
|
|
|
|
|
|
local $@; |
|
0
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
0
|
|
|
|
|
|
eval { $e->sendlog('FATAL') }; |
|
0
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
|
exit $e->exit_code; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub SIGWARN { |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# skip AE callback error warning |
87
|
0
|
0
|
|
0
|
1
|
|
return if $_[0] =~ /\AEV: error in callback/sm; |
88
|
|
|
|
|
|
|
|
89
|
0
|
|
|
|
|
|
my $e = Pcore::Core::Exception::Object->new( $_[0], level => 'WARN', skip_frames => 1, with_trace => 1 ); |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
{ |
92
|
0
|
|
|
|
|
|
local $@; |
|
0
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
0
|
|
|
|
|
|
$e->sendlog('WARN'); |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
0
|
|
|
|
|
|
return; # skip standard warn behaviour |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# die without trace |
101
|
|
|
|
|
|
|
sub croak { |
102
|
0
|
|
|
0
|
0
|
|
my $msg; |
103
|
|
|
|
|
|
|
|
104
|
0
|
0
|
|
|
|
|
if (@_) { |
|
|
0
|
|
|
|
|
|
105
|
0
|
0
|
|
|
|
|
if ( @_ > 1 ) { |
106
|
0
|
|
|
|
|
|
$msg = join q[], @_; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
else { |
109
|
0
|
|
|
|
|
|
$msg = $_[0]; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
elsif ($@) { |
113
|
0
|
|
|
|
|
|
$msg = $@ . ' ...propagated'; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
else { |
116
|
0
|
|
|
|
|
|
$msg = 'Died'; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
my $e = Pcore::Core::Exception::Object->new( $msg, level => 'ERROR', skip_frames => 1, with_trace => 0 ); |
120
|
|
|
|
|
|
|
|
121
|
0
|
|
|
|
|
|
return CORE::die $e; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# warn without trace |
125
|
|
|
|
|
|
|
sub cluck { |
126
|
0
|
|
|
0
|
0
|
|
my $msg; |
127
|
|
|
|
|
|
|
|
128
|
0
|
0
|
|
|
|
|
if (@_) { |
|
|
0
|
|
|
|
|
|
129
|
0
|
0
|
|
|
|
|
if ( @_ > 1 ) { |
130
|
0
|
|
|
|
|
|
$msg = join q[], @_; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
else { |
133
|
0
|
|
|
|
|
|
$msg = $_[0]; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
elsif ($@) { |
137
|
0
|
|
|
|
|
|
$msg = $@ . ' ...caught'; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
else { |
140
|
0
|
|
|
|
|
|
$msg = q[Warning: something's wrong]; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
my $e = Pcore::Core::Exception::Object->new( $msg, level => 'WARN', skip_frames => 1, with_trace => 0 ); |
144
|
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
return CORE::warn $e; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
1; |
149
|
|
|
|
|
|
|
## -----SOURCE FILTER LOG BEGIN----- |
150
|
|
|
|
|
|
|
## |
151
|
|
|
|
|
|
|
## PerlCritic profile "pcore-script" policy violations: |
152
|
|
|
|
|
|
|
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+ |
153
|
|
|
|
|
|
|
## | Sev. | Lines | Policy | |
154
|
|
|
|
|
|
|
## |======+======================+================================================================================================================| |
155
|
|
|
|
|
|
|
## | 3 | 53, 64, 75, 92 | Variables::RequireInitializationForLocalVars - "local" variable not initialized | |
156
|
|
|
|
|
|
|
## |------+----------------------+----------------------------------------------------------------------------------------------------------------| |
157
|
|
|
|
|
|
|
## | 3 | 55, 66, 77 | ErrorHandling::RequireCheckingReturnValueOfEval - Return value of eval not tested | |
158
|
|
|
|
|
|
|
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+ |
159
|
|
|
|
|
|
|
## |
160
|
|
|
|
|
|
|
## -----SOURCE FILTER LOG END----- |
161
|
|
|
|
|
|
|
__END__ |
162
|
|
|
|
|
|
|
=pod |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=encoding utf8 |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=head1 Pcore::Core::Exception |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Pharaoh::Core::Sig - signals management for Pharaoh::Core. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
This package is part of Pharaoh::Core. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head1 EXPORTS |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=head2 CORE::GLOBAL::exit |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Common exit() family functions behaviour: |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=over |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=item * threads->exit() and CORE::exit() is unhandled in threads and perform exit according to threads->set_thread_exit_only; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item * CORE::exit() is unhandled; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=back |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head1 SIGNALS |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head2 SIGDIE |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Standart $SIG{__DIE__} exceptions handler. Use following code to redefined callback: |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
local $SIG{__DIE__}; # Redefine handler locally, no callback defined, $SIG{__DIE__} will be ignored |
193
|
|
|
|
|
|
|
local $SIG{__DIE__} = sub { # Ditto with callback defined |
194
|
|
|
|
|
|
|
...do something... |
195
|
|
|
|
|
|
|
}; |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=over |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item * C<$SIG{__DIE__}> called from eval block produce ERROR log with stack trace and returns; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=item * C<$SIG{__DIE__}> called from NOT eval block produce FATAL log with stack trace and exit from process / thread; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item * C<__ALRM__> exception from eval ignored; |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item * C<__ALRM__> exception from NOT eval block produce FATAL exception; |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item * C<__EXIT__> exception is ignored totally and can be processed in your code. See CORE::GLOBAL::exit for example; |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=item * Calling die() in $SIG{__DIE__} will overwrite $@ and exit $SIG{__DIE__} immidiately; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item * Overriding die will only catch actual calls to die, not run-time errors; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=back |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head2 SIGWARN |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Standart $SIG{__WARN__} handler. Produce standart log event on WARN level with stack backtace. To avoid call use following in your code: |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
local $SIG{__WARN__} = sub { }; # Redefine callback locally |
220
|
|
|
|
|
|
|
local $SIG{__WARN__} = undef; # Restore standart behaviour in current block |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head2 SIGALRM |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
Standart $SIG{ALRM} handler. Produce C<__ALRM__> exception. To redefine callback use following in your code: |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
local $SIG{ALRM} = sub { }; # Redefine callback locally |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
or use this alarm - safe code: |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
my $orig_alarm = 0; |
231
|
|
|
|
|
|
|
eval{ |
232
|
|
|
|
|
|
|
$orig_alarm = alarm 5; # Store previous alarm() timer internally |
233
|
|
|
|
|
|
|
...some code here... |
234
|
|
|
|
|
|
|
}; |
235
|
|
|
|
|
|
|
alarm $orig_alarm; # Restore previous timer |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
if($@ =~ /^__ALRM__/){ |
238
|
|
|
|
|
|
|
...do something on alarm... |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
NOTES |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=over |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=item * If $SIG{ALRM} not defined - process will killed on alarm. SIG{__DIE__} don't handle alarm exception; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item * Alarm - safe code must restore previous alarm timer at the end of execution. We can't control bad written code in other modules, so be ready that you alarm timers will not work if you use not alarm - safe modules; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=item * alarm() works on MSWin and in threads as expected; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=item * You must remove alarm timer immidiately after end of eval block (not in block), because if evaluated code will die - eval block will be broken and your alarm will not be removed; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=item * alarm() call on MSWin didn't return amount of time remaining for previous timer. So chained timers on MSWin NOT WORKED. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=back |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=cut |