… | |
… | |
24 | |
24 | |
25 | =cut |
25 | =cut |
26 | |
26 | |
27 | package AnyEvent::Debug; |
27 | package AnyEvent::Debug; |
28 | |
28 | |
|
|
29 | use B (); |
29 | use Carp (); |
30 | use Carp (); |
30 | use Errno (); |
31 | use Errno (); |
31 | |
32 | |
32 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
33 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
33 | use AnyEvent::Util (); |
34 | use AnyEvent::Util (); |
34 | use AnyEvent::Socket (); |
35 | use AnyEvent::Socket (); |
35 | use AnyEvent::Log (); |
36 | use AnyEvent::Log (); |
36 | |
37 | |
|
|
38 | our $TRACE = 1; # trace status |
|
|
39 | |
37 | our ($TRACE_LOGGER, $TRACE_ENABLED); |
40 | our ($TRACE_LOGGER, $TRACE_ENABLED); |
38 | |
41 | |
39 | # cache often-used strings, purely to save memory, at the expense of speed |
42 | # cache often-used strings, purely to save memory, at the expense of speed |
40 | our %STRCACHE; |
43 | our %STRCACHE; |
41 | |
44 | |
42 | =item $shell = AnyEvent;::Debug::shell $host, $service |
45 | =item $shell = AnyEvent::Debug::shell $host, $service |
43 | |
46 | |
44 | This function binds on the given host and service port and returns a |
47 | This function binds on the given host and service port and returns a |
45 | shell object, which determines the lifetime of the shell. Any number |
48 | shell object, which determines the lifetime of the shell. Any number |
46 | of conenctions are accepted on the port, and they will give you a very |
49 | of conenctions are accepted on the port, and they will give you a very |
47 | primitive shell that simply executes every line you enter. |
50 | primitive shell that simply executes every line you enter. |
48 | |
51 | |
49 | All commands will be executed "blockingly" with the socket C<select>ed for |
52 | All commands will be executed "blockingly" with the socket C<select>ed for |
50 | output. For a less "blocking" interface see L<Coro::Debug>. |
53 | output. For a less "blocking" interface see L<Coro::Debug>. |
51 | |
54 | |
52 | The commands will be executed in the C<AnyEvent::Debug::shell> package, |
55 | The commands will be executed in the C<AnyEvent::Debug::shell> package, |
53 | which currently has "help", "wl" and "wlv" commands, and can be freely |
56 | which currently has "help" and a few other commands, and can be freely |
54 | modified by all shells. Code is evaluated under C<use strict 'subs'>. |
57 | modified by all shells. Code is evaluated under C<use strict 'subs'>. |
55 | |
58 | |
56 | Consider the beneficial aspects of using more global (our) variables than |
59 | Every shell has a logging context (C<$LOGGER>) that is attached to |
57 | local ones (my) in package scope: Earlier all my modules tended to hide |
60 | C<$AnyEvent::Log::COLLECT>), which is especially useful to gether debug |
58 | internal variables inside C<my> variables, so users couldn't accidentally |
61 | and trace messages. |
59 | access them. Having interactive access to your programs changed that: |
62 | |
|
|
63 | As a general programming guide, consider the beneficial aspects of |
|
|
64 | using more global (C<our>) variables than local ones (C<my>) in package |
|
|
65 | scope: Earlier all my modules tended to hide internal variables inside |
|
|
66 | C<my> variables, so users couldn't accidentally access them. Having |
|
|
67 | interactive access to your programs changed that: having internal |
60 | having internal variables still in the global scope means you can debug |
68 | variables still in the global scope means you can debug them easier. |
61 | them easier. |
|
|
62 | |
69 | |
63 | As no authentication is done, in most cases it is best not to use a TCP |
70 | As no authentication is done, in most cases it is best not to use a TCP |
64 | port, but a unix domain socket, whcih can be put wherever you can access |
71 | port, but a unix domain socket, whcih can be put wherever you can access |
65 | it, but not others: |
72 | it, but not others: |
66 | |
73 | |
… | |
… | |
88 | telnet localhost 1357 |
95 | telnet localhost 1357 |
89 | |
96 | |
90 | =cut |
97 | =cut |
91 | |
98 | |
92 | sub shell($$) { |
99 | sub shell($$) { |
|
|
100 | local $TRACE = 0; |
|
|
101 | |
93 | AnyEvent::Socket::tcp_server $_[0], $_[1], sub { |
102 | AnyEvent::Socket::tcp_server $_[0], $_[1], sub { |
94 | my ($fh, $host, $port) = @_; |
103 | my ($fh, $host, $port) = @_; |
95 | |
104 | |
96 | syswrite $fh, "Welcome, $host:$port, use 'help' for more info!\015\012> "; |
105 | syswrite $fh, "Welcome, $host:$port, use 'help' for more info!\015\012> "; |
97 | my $rbuf; |
106 | my $rbuf; |
|
|
107 | |
|
|
108 | my $logger = new AnyEvent::Log::Ctx |
|
|
109 | log_cb => sub { |
|
|
110 | syswrite $fh, shift; |
|
|
111 | 0 |
|
|
112 | }; |
|
|
113 | |
|
|
114 | my $logger_guard = AnyEvent::Util::guard { |
|
|
115 | $AnyEvent::Log::COLLECT->detach ($logger); |
|
|
116 | }; |
|
|
117 | $AnyEvent::Log::COLLECT->attach ($logger); |
|
|
118 | |
|
|
119 | local $TRACE = 0; |
98 | my $rw; $rw = AE::io $fh, 0, sub { |
120 | my $rw; $rw = AE::io $fh, 0, sub { |
99 | my $len = sysread $fh, $rbuf, 1024, length $rbuf; |
121 | my $len = sysread $fh, $rbuf, 1024, length $rbuf; |
|
|
122 | |
|
|
123 | $logger_guard if 0; # reference it |
100 | |
124 | |
101 | if (defined $len ? $len == 0 : $! != Errno::EAGAIN) { |
125 | if (defined $len ? $len == 0 : $! != Errno::EAGAIN) { |
102 | undef $rw; |
126 | undef $rw; |
103 | } else { |
127 | } else { |
104 | while ($rbuf =~ s/^(.*)\015?\012//) { |
128 | while ($rbuf =~ s/^(.*)\015?\012//) { |
… | |
… | |
110 | syswrite $fh, "sorry, no... if you want to execute exit, try CORE::exit.\015\012"; |
134 | syswrite $fh, "sorry, no... if you want to execute exit, try CORE::exit.\015\012"; |
111 | } else { |
135 | } else { |
112 | package AnyEvent::Debug::shell; |
136 | package AnyEvent::Debug::shell; |
113 | |
137 | |
114 | no strict 'vars'; |
138 | no strict 'vars'; |
|
|
139 | local $LOGGER = $logger; |
115 | my $old_stdout = select $fh; |
140 | my $old_stdout = select $fh; |
116 | local $| = 1; |
141 | local $| = 1; |
117 | |
142 | |
118 | my @res = eval $line; |
143 | my @res = eval $line; |
119 | |
144 | |
… | |
… | |
137 | } |
162 | } |
138 | |
163 | |
139 | { |
164 | { |
140 | package AnyEvent::Debug::shell; |
165 | package AnyEvent::Debug::shell; |
141 | |
166 | |
|
|
167 | our $LOGGER; |
|
|
168 | |
142 | sub help() { |
169 | sub help() { |
143 | <<EOF |
170 | <<EOF |
144 | help this command |
171 | help this command |
145 | wr [level] sets wrap level to level (or toggles if missing) |
172 | wr [level] sets wrap level to level (or toggles if missing) |
146 | v [level] sets verbosity (or toggles if missing) |
173 | v [level] sets verbosity (or toggles between 0 and 9 if missing) |
147 | wl 'regex' print wrapped watchers matching the regex (or all if missing) |
174 | wl 'regex' print wrapped watchers matching the regex (or all if missing) |
148 | w id,... prints the watcher with the given ids in more detail |
175 | i id,... prints the watcher with the given ids in more detail |
|
|
176 | t enable tracing for newly created watchers (enabled by default) |
|
|
177 | ut disable tracing for newly created watchers |
|
|
178 | t id,... enable tracing for the given watcher (enabled by default) |
|
|
179 | ut id,... disable tracing for the given watcher |
|
|
180 | w id,... converts the watcher ids to watcher objects (for scripting) |
149 | EOF |
181 | EOF |
150 | } |
182 | } |
151 | |
183 | |
152 | sub wl(;$) { |
184 | sub wl(;$) { |
153 | my $re = @_ ? qr<$_[0]>i : qr<.>; |
185 | my $re = @_ ? qr<$_[0]>i : qr<.>; |
… | |
… | |
161 | } |
193 | } |
162 | |
194 | |
163 | join "", map "$res{$_} $_\n", sort keys %res |
195 | join "", map "$res{$_} $_\n", sort keys %res |
164 | } |
196 | } |
165 | |
197 | |
166 | sub w(@) { |
198 | sub w { |
167 | my $res; |
199 | map { |
168 | |
|
|
169 | for my $id (@_) { |
|
|
170 | if (my $w = $AnyEvent::Debug::Wrapped{$id}) { |
200 | $AnyEvent::Debug::Wrapped{$_} || do { |
171 | $res .= "$id $w\n" . $w->verbose; |
|
|
172 | } else { |
|
|
173 | $res .= "$id: no such wrapped watcher.\n"; |
201 | print "$_: no such wrapped watcher.\n"; |
|
|
202 | () |
174 | } |
203 | } |
175 | } |
204 | } @_ |
|
|
205 | } |
176 | |
206 | |
177 | $res |
207 | sub i { |
|
|
208 | join "", |
|
|
209 | map $_->id . " $_\n" . $_->verbose . "\n", |
|
|
210 | &w |
178 | } |
211 | } |
179 | |
212 | |
180 | sub wr { |
213 | sub wr { |
181 | AnyEvent::Debug::wrap (@_); |
214 | AnyEvent::Debug::wrap (@_); |
182 | |
215 | |
183 | "wrap level now $AnyEvent::Debug::WRAP_LEVEL" |
216 | "wrap level now $AnyEvent::Debug::WRAP_LEVEL" |
184 | } |
217 | } |
185 | |
218 | |
|
|
219 | sub t { |
|
|
220 | if (@_) { |
|
|
221 | @_ = &w; |
|
|
222 | $_->trace (1) |
|
|
223 | for @_; |
|
|
224 | "tracing enabled for @_." |
|
|
225 | } else { |
|
|
226 | $AnyEvent::Debug::TRACE = 1; |
|
|
227 | "tracing for newly created watchers is now enabled." |
|
|
228 | } |
|
|
229 | } |
|
|
230 | |
|
|
231 | sub u { |
|
|
232 | if (@_) { |
|
|
233 | @_ = &w; |
|
|
234 | $_->trace (0) |
|
|
235 | for @_; |
|
|
236 | "tracing disabled for @_." |
|
|
237 | } else { |
|
|
238 | $AnyEvent::Debug::TRACE = 0; |
|
|
239 | "tracing for newly created watchers is now disabled." |
|
|
240 | } |
|
|
241 | } |
|
|
242 | |
186 | sub v { |
243 | sub v { |
187 | #TODO |
244 | $LOGGER->level (@_ ? $_[0] : $LOGGER->[1] ? 0 : 9); |
188 | $AnyEvent::VERBOSE = @_ ? shift : $AnyEvent::VERBOSE ? 0 : 9; |
|
|
189 | |
245 | |
190 | "verbosity level now $AnyEvent::VEBROSE" |
246 | "verbose logging is now " . ($LOGGER->[1] ? "enabled" : "disabled") . "." |
191 | } |
247 | } |
192 | } |
248 | } |
193 | |
249 | |
194 | =item AnyEvent::Debug::wrap [$level] |
250 | =item AnyEvent::Debug::wrap [$level] |
195 | |
251 | |
… | |
… | |
201 | C<$ENV{PERL_ANYEVENT_DEBUG_WRAP}> specifies. |
257 | C<$ENV{PERL_ANYEVENT_DEBUG_WRAP}> specifies. |
202 | |
258 | |
203 | A level of C<0> disables wrapping, i.e. AnyEvent works normally, and in |
259 | A level of C<0> disables wrapping, i.e. AnyEvent works normally, and in |
204 | its most efficient mode. |
260 | its most efficient mode. |
205 | |
261 | |
206 | A level of C<1> enables wrapping, which replaces all watchers by |
262 | A level of C<1> or higher enables wrapping, which replaces all watchers |
207 | AnyEvent::Debug::Wrapped objects, stores the location where a watcher |
263 | by AnyEvent::Debug::Wrapped objects, stores the location where a |
208 | was created and wraps the callback to log all invocations at "trace" |
264 | watcher was created and wraps the callback to log all invocations at |
|
|
265 | "trace" loglevel if tracing is enabled fore the watcher. The initial |
|
|
266 | state of tracing when creating a watcher is taken from the global |
|
|
267 | variable C<$AnyEvent:Debug::TRACE>. The default value of that variable |
|
|
268 | is C<1>, but it can make sense to set it to C<0> and then do C<< local |
|
|
269 | $AnyEvent::Debug::TRACE = 1 >> in a block where you create "interesting" |
|
|
270 | watchers. Tracing can also be enabled and disabled later by calling the |
|
|
271 | watcher's C<trace> method. |
|
|
272 | |
209 | loglevel. The wrapper will also count how many times the callback was |
273 | The wrapper will also count how many times the callback was invoked and |
210 | invoked and will record up to ten runtime errors with corresponding |
274 | will record up to ten runtime errors with corresponding backtraces. It |
211 | backtraces. It will also log runtime errors at "error" loglevel. |
275 | will also log runtime errors at "error" loglevel. |
212 | |
276 | |
213 | To see the trace messages, you can invoke your program with |
277 | To see the trace messages, you can invoke your program with |
214 | C<PERL_ANYEVENT_VERBOSE=9>, or you can use AnyEvent::Log to divert |
278 | C<PERL_ANYEVENT_VERBOSE=9>, or you can use AnyEvent::Log to divert |
215 | the trace messages in any way you like (the EXAMPLES section in |
279 | the trace messages in any way you like (the EXAMPLES section in |
216 | L<AnyEvent::Log> has some examples). |
280 | L<AnyEvent::Log> has some examples). |
… | |
… | |
218 | A level of C<2> does everything that level C<1> does, but also stores a |
282 | A level of C<2> does everything that level C<1> does, but also stores a |
219 | full backtrace of the location the watcher was created, which slows down |
283 | full backtrace of the location the watcher was created, which slows down |
220 | watcher creation considerably. |
284 | watcher creation considerably. |
221 | |
285 | |
222 | Every wrapped watcher will be linked into C<%AnyEvent::Debug::Wrapped>, |
286 | Every wrapped watcher will be linked into C<%AnyEvent::Debug::Wrapped>, |
223 | with its address as key. The C<wl> command in the debug shell cna be used |
287 | with its address as key. The C<wl> command in the debug shell can be used |
224 | to list watchers. |
288 | to list watchers. |
225 | |
289 | |
226 | Instrumenting can increase the size of each watcher multiple times, and, |
290 | Instrumenting can increase the size of each watcher multiple times, and, |
227 | especially when backtraces are involved, also slows down watcher creation |
291 | especially when backtraces are involved, also slows down watcher creation |
228 | a lot. |
292 | a lot. |
… | |
… | |
257 | undef $POST_DETECT; |
321 | undef $POST_DETECT; |
258 | return unless $WRAP_LEVEL; |
322 | return unless $WRAP_LEVEL; |
259 | |
323 | |
260 | (my $level, $WRAP_LEVEL) = ($WRAP_LEVEL, undef); |
324 | (my $level, $WRAP_LEVEL) = ($WRAP_LEVEL, undef); |
261 | |
325 | |
262 | require AnyEvent::Strict; |
326 | require AnyEvent::Strict unless $AnyEvent::Strict::VERSION; |
263 | |
327 | |
264 | AnyEvent::post_detect { # make sure we run after AnyEvent::Strict |
328 | AnyEvent::post_detect { # make sure we run after AnyEvent::Strict |
265 | wrap ($level); |
329 | wrap ($level); |
266 | }; |
330 | }; |
267 | }; |
331 | }; |
… | |
… | |
308 | =cut |
372 | =cut |
309 | |
373 | |
310 | sub cb2str($) { |
374 | sub cb2str($) { |
311 | my $cb = shift; |
375 | my $cb = shift; |
312 | |
376 | |
313 | require B; |
|
|
314 | |
|
|
315 | "CODE" eq ref $cb |
377 | "CODE" eq ref $cb |
316 | or return "$cb"; |
378 | or return "$cb"; |
317 | |
379 | |
|
|
380 | eval { |
318 | my $cv = B::svref_2object ($cb); |
381 | my $cv = B::svref_2object ($cb); |
319 | |
382 | |
320 | my $gv = $cv->GV |
383 | my $gv = $cv->GV |
321 | or return "$cb"; |
384 | or return "$cb"; |
322 | |
385 | |
|
|
386 | my $name = $gv->NAME; |
|
|
387 | |
323 | return (AnyEvent::Debug::path2mod $gv->FILE) . ":" . $gv->LINE |
388 | return (AnyEvent::Debug::path2mod $gv->FILE) . ":" . $gv->LINE |
324 | if $gv->NAME eq "__ANON__"; |
389 | if $name eq "__ANON__"; |
325 | |
390 | |
326 | return $gv->STASH->NAME . "::" . $gv->NAME; |
391 | $gv->STASH->NAME . "::" . $name; |
|
|
392 | } || "$cb" |
327 | } |
393 | } |
328 | |
394 | |
329 | sub sv2str($) { |
395 | sub sv2str($) { |
330 | if (ref $_[0]) { |
396 | if (ref $_[0]) { |
331 | if (ref $_[0] eq "CODE") { |
397 | if (ref $_[0] eq "CODE") { |
… | |
… | |
344 | |
410 | |
345 | =item AnyEvent::Debug::backtrace [$skip] |
411 | =item AnyEvent::Debug::backtrace [$skip] |
346 | |
412 | |
347 | Creates a backtrace (actually an AnyEvent::Debug::Backtrace object |
413 | Creates a backtrace (actually an AnyEvent::Debug::Backtrace object |
348 | that you can stringify), not unlike the Carp module would. Unlike the |
414 | that you can stringify), not unlike the Carp module would. Unlike the |
349 | Carp module it resolves some references (euch as callbacks) to more |
415 | Carp module it resolves some references (such as callbacks) to more |
350 | user-friendly strings, has a more succinct output format and most |
416 | user-friendly strings, has a more succinct output format and most |
351 | importantly: doesn't leak memory like hell. |
417 | importantly: doesn't leak memory like hell. |
352 | |
418 | |
353 | The reason it creates an object is to save time, as formatting can be |
419 | The reason it creates an object is to save time, as formatting can be |
354 | done at a later time. Still, creating a backtrace is a relatively slow |
420 | done at a later time. Still, creating a backtrace is a relatively slow |
… | |
… | |
410 | *$name = sub { |
476 | *$name = sub { |
411 | my ($self, %arg) = @_; |
477 | my ($self, %arg) = @_; |
412 | |
478 | |
413 | my $w; |
479 | my $w; |
414 | |
480 | |
|
|
481 | my $t = $TRACE; |
|
|
482 | |
415 | my ($pkg, $file, $line, $sub); |
483 | my ($pkg, $file, $line, $sub); |
416 | |
484 | |
417 | $w = 0; |
485 | $w = 0; |
418 | do { |
486 | do { |
419 | ($pkg, $file, $line) = caller $w++; |
487 | ($pkg, $file, $line) = caller $w++; |
… | |
… | |
425 | $arg{cb} = sub { |
493 | $arg{cb} = sub { |
426 | ++$w->{called}; |
494 | ++$w->{called}; |
427 | |
495 | |
428 | local $TRACE_CUR = $w; |
496 | local $TRACE_CUR = $w; |
429 | |
497 | |
430 | $TRACE_LOGGER->("enter $w") if $TRACE_ENABLED; |
498 | $TRACE_LOGGER->("enter $w") if $TRACE_ENABLED && $t; |
431 | eval { |
499 | eval { |
432 | local $SIG{__DIE__} = sub { |
500 | local $SIG{__DIE__} = sub { |
433 | die $_[0] . AnyEvent::Debug::backtrace |
501 | die $_[0] . AnyEvent::Debug::backtrace |
434 | if defined $^S; |
502 | if defined $^S; |
435 | }; |
503 | }; |
436 | &$cb; |
504 | &$cb; |
437 | }; |
505 | }; |
438 | if ($@) { |
506 | if ($@) { |
|
|
507 | my $err = "$@"; |
439 | push @{ $w->{error} }, [AE::now, "$@"] |
508 | push @{ $w->{error} }, [AE::now, $err] |
440 | if @{ $w->{error} } < 10; |
509 | if @{ $w->{error} } < 10; |
441 | AE::log die => "($w) $@" |
510 | AE::log die => "($w) $err" |
442 | or warn "($w) $@"; |
511 | or warn "($w) $err"; |
443 | } |
512 | } |
444 | $TRACE_LOGGER->("leave $w") if $TRACE_ENABLED; |
513 | $TRACE_LOGGER->("leave $w") if $TRACE_ENABLED && $t; |
445 | }; |
514 | }; |
446 | |
515 | |
447 | $self = bless { |
516 | $self = bless { |
448 | type => $name, |
517 | type => $name, |
449 | w => $self->$super (%arg), |
518 | w => $self->$super (%arg), |
… | |
… | |
453 | cur => "$TRACE_CUR", |
522 | cur => "$TRACE_CUR", |
454 | now => AE::now, |
523 | now => AE::now, |
455 | arg => \%arg, |
524 | arg => \%arg, |
456 | cb => $cb, |
525 | cb => $cb, |
457 | called => 0, |
526 | called => 0, |
|
|
527 | rt => \$t, |
458 | }, "AnyEvent::Debug::Wrapped"; |
528 | }, "AnyEvent::Debug::Wrapped"; |
459 | |
529 | |
460 | delete $arg{cb}; |
530 | delete $arg{cb}; |
461 | |
531 | |
462 | $self->{bt} = AnyEvent::Debug::backtrace 1 |
532 | $self->{bt} = AnyEvent::Debug::backtrace 1 |
463 | if $WRAP_LEVEL >= 2; |
533 | if $WRAP_LEVEL >= 2; |
464 | |
534 | |
465 | Scalar::Util::weaken ($w = $self); |
535 | Scalar::Util::weaken ($w = $self); |
466 | Scalar::Util::weaken ($AnyEvent::Debug::Wrapped{Scalar::Util::refaddr $self} = $self); |
536 | Scalar::Util::weaken ($AnyEvent::Debug::Wrapped{Scalar::Util::refaddr $self} = $self); |
467 | |
537 | |
468 | $TRACE_LOGGER->("creat $w") if $TRACE_ENABLED; |
538 | $TRACE_LOGGER->("creat $w") if $TRACE_ENABLED && $t; |
469 | |
539 | |
470 | $self |
540 | $self |
471 | }; |
541 | }; |
472 | } |
542 | } |
473 | } |
543 | } |
… | |
… | |
479 | All watchers created while the wrap level is non-zero will be wrapped |
549 | All watchers created while the wrap level is non-zero will be wrapped |
480 | inside an AnyEvent::Debug::Wrapped object. The address of the |
550 | inside an AnyEvent::Debug::Wrapped object. The address of the |
481 | wrapped watcher will become its ID - every watcher will be stored in |
551 | wrapped watcher will become its ID - every watcher will be stored in |
482 | C<$AnyEvent::Debug::Wrapped{$id}>. |
552 | C<$AnyEvent::Debug::Wrapped{$id}>. |
483 | |
553 | |
484 | These wrapper objects, as of now, can be stringified, and you can call the |
554 | These wrapper objects can be stringified and have some methods defined on |
485 | C<< ->verbose >> method to get a multiline string describing the watcher |
555 | them. |
486 | in great detail, but otherwise has no other public methods. |
|
|
487 | |
556 | |
488 | For debugging, of course, it can be helpful to look into these objects, |
557 | For debugging, of course, it can be helpful to look into these objects, |
489 | which is why this is documented here, but this might change at any time in |
558 | which is why this is documented here, but this might change at any time in |
490 | future versions. |
559 | future versions. |
491 | |
560 | |
… | |
… | |
500 | now => the timestamp (AE::now) when the watcher was created |
569 | now => the timestamp (AE::now) when the watcher was created |
501 | arg => the arguments used to create the watcher (sans C<cb>) |
570 | arg => the arguments used to create the watcher (sans C<cb>) |
502 | cb => the original callback used to create the watcher |
571 | cb => the original callback used to create the watcher |
503 | called => the number of times the callback was called |
572 | called => the number of times the callback was called |
504 | |
573 | |
|
|
574 | Each object supports the following mehtods (warning: these are only |
|
|
575 | available on wrapped watchers, so are best for interactive use via the |
|
|
576 | debug shell). |
|
|
577 | |
|
|
578 | =over 4 |
|
|
579 | |
505 | =cut |
580 | =cut |
506 | |
581 | |
507 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
582 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
508 | |
583 | |
509 | use overload |
584 | use overload |
… | |
… | |
523 | . (AnyEvent::Debug::cb2str $_[0]{cb}) |
598 | . (AnyEvent::Debug::cb2str $_[0]{cb}) |
524 | }; |
599 | }; |
525 | }, |
600 | }, |
526 | fallback => 1, |
601 | fallback => 1, |
527 | ; |
602 | ; |
|
|
603 | |
|
|
604 | =item $w->id |
|
|
605 | |
|
|
606 | Returns the numerical id of the watcher, as used in the debug shell. |
|
|
607 | |
|
|
608 | =cut |
|
|
609 | |
|
|
610 | sub id { |
|
|
611 | Scalar::Util::refaddr shift |
|
|
612 | } |
|
|
613 | |
|
|
614 | =item $w->verbose |
|
|
615 | |
|
|
616 | Returns a multiline textual description of the watcher, including the |
|
|
617 | first ten exceptions caught while executing the callback. |
|
|
618 | |
|
|
619 | =cut |
528 | |
620 | |
529 | sub verbose { |
621 | sub verbose { |
530 | my ($self) = @_; |
622 | my ($self) = @_; |
531 | |
623 | |
532 | my $res = "type: $self->{type} watcher\n" |
624 | my $res = "type: $self->{type} watcher\n" |
… | |
… | |
534 | . "created: " . (AnyEvent::Log::ft $self->{now}) . " ($self->{now})\n" |
626 | . "created: " . (AnyEvent::Log::ft $self->{now}) . " ($self->{now})\n" |
535 | . "file: ${ $self->{rfile} }\n" |
627 | . "file: ${ $self->{rfile} }\n" |
536 | . "line: $self->{line}\n" |
628 | . "line: $self->{line}\n" |
537 | . "subname: $self->{sub}\n" |
629 | . "subname: $self->{sub}\n" |
538 | . "context: $self->{cur}\n" |
630 | . "context: $self->{cur}\n" |
|
|
631 | . "tracing: " . (${ $self->{rt} } ? "enabled" : "disabled") . "\n" |
539 | . "cb: $self->{cb} (" . (AnyEvent::Debug::cb2str $self->{cb}) . ")\n" |
632 | . "cb: $self->{cb} (" . (AnyEvent::Debug::cb2str $self->{cb}) . ")\n" |
540 | . "invoked: $self->{called} times\n"; |
633 | . "invoked: $self->{called} times\n"; |
541 | |
634 | |
542 | if (exists $self->{bt}) { |
635 | if (exists $self->{bt}) { |
543 | $res .= "created\n$self->{bt}"; |
636 | $res .= "created\n$self->{bt}"; |
… | |
… | |
551 | } |
644 | } |
552 | |
645 | |
553 | $res |
646 | $res |
554 | } |
647 | } |
555 | |
648 | |
|
|
649 | =item $w->trace ($on) |
|
|
650 | |
|
|
651 | Enables (C<$on> is true) or disables (C<$on> is false) tracing on this |
|
|
652 | watcher. |
|
|
653 | |
|
|
654 | To get tracing messages, both the global logging settings must have trace |
|
|
655 | messages enabled for the context C<AnyEvent::Debug> and tracing must be |
|
|
656 | enabled for the wrapped watcher. |
|
|
657 | |
|
|
658 | To enable trace messages globally, the simplest way is to start the |
|
|
659 | program with C<PERL_ANYEVENT_VERBOSE=9> in the environment. |
|
|
660 | |
|
|
661 | Tracing for each individual watcher is enabled by default (unless |
|
|
662 | C<$AnyEvent::Debug::TRACE> has been set to false). |
|
|
663 | |
|
|
664 | =cut |
|
|
665 | |
|
|
666 | sub trace { |
|
|
667 | ${ $_[0]{rt} } = $_[1]; |
|
|
668 | } |
|
|
669 | |
556 | sub DESTROY { |
670 | sub DESTROY { |
557 | $TRACE_LOGGER->("dstry $_[0]") if $TRACE_ENABLED; |
671 | $TRACE_LOGGER->("dstry $_[0]") if $TRACE_ENABLED && ${ $_[0]{rt} }; |
558 | |
672 | |
559 | delete $AnyEvent::Debug::Wrapped{Scalar::Util::refaddr $_[0]}; |
673 | delete $AnyEvent::Debug::Wrapped{Scalar::Util::refaddr $_[0]}; |
560 | } |
674 | } |
|
|
675 | |
|
|
676 | =back |
|
|
677 | |
|
|
678 | =cut |
561 | |
679 | |
562 | package AnyEvent::Debug::Backtrace; |
680 | package AnyEvent::Debug::Backtrace; |
563 | |
681 | |
564 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
682 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
565 | |
683 | |
… | |
… | |
572 | for (@$self) { |
690 | for (@$self) { |
573 | my ($rpath, $line, $sub) = @$_; |
691 | my ($rpath, $line, $sub) = @$_; |
574 | |
692 | |
575 | $rpath = (AnyEvent::Debug::path2mod $$rpath) . " line $line"; |
693 | $rpath = (AnyEvent::Debug::path2mod $$rpath) . " line $line"; |
576 | $modlen = length $rpath if $modlen < length $rpath; |
694 | $modlen = length $rpath if $modlen < length $rpath; |
|
|
695 | |
|
|
696 | $sub =~ s/\r/\\r/g; |
|
|
697 | $sub =~ s/\n/\\n/g; |
|
|
698 | $sub =~ s/([\x00-\x1f\x7e-\xff])/sprintf "\\x%02x", ord $1/ge; |
|
|
699 | $sub =~ s/([^\x20-\x7e])/sprintf "\\x{%x}", ord $1/ge; |
577 | |
700 | |
578 | push @bt, [$rpath, $sub]; |
701 | push @bt, [$rpath, $sub]; |
579 | } |
702 | } |
580 | |
703 | |
581 | join "", |
704 | join "", |
… | |
… | |
586 | use overload |
709 | use overload |
587 | '""' => \&as_string, |
710 | '""' => \&as_string, |
588 | fallback => 1, |
711 | fallback => 1, |
589 | ; |
712 | ; |
590 | |
713 | |
591 | 1; |
|
|
592 | |
|
|
593 | =head1 AUTHOR |
714 | =head1 AUTHOR |
594 | |
715 | |
595 | Marc Lehmann <schmorp@schmorp.de> |
716 | Marc Lehmann <schmorp@schmorp.de> |
596 | http://home.schmorp.de/ |
717 | http://anyevent.schmorp.de |
597 | |
718 | |
598 | =cut |
719 | =cut |
599 | |
720 | |
|
|
721 | 1 |
|
|
722 | |