clueless newbie has asked for the wisdom of the Perl Monks concerning the following question:
Greeting Monks,
I’m experimenting with using the built-in `DB` package to build a lightweight call tracer. I’ve previously done something similar using **Hook::LexWrap** and **Module::Info**, but this time I’d like to catch **entry and exit** events for subroutines directly through Perl’s built-in debugging interface.
Here’s the minimal prototype I’ve tried:
+ package Devel::Lite; use strict; use warnings; use Time::HiRes (); our $IN_TRACE = 0; sub DB::sub { return &$DB::sub(@_) if $IN_TRACE; local $IN_TRACE = 1; my $sub = $DB::sub; my @args = @_; print STDERR ">> entering $sub\n"; my @ret; eval { @ret = &$sub(@args); }; print STDERR "<< leaving $sub\n"; die $@ if $@; return wantarray ? @ret : $ret[0]; } 1;
Then I run it like this:
perl -I. -d:TobyLite -e "sub x { print qq{okay\n}; } x();"
…but it loops endlessly and never reaches my test sub.
If I insert a print inside the loop, I see repeated `"Time::HiRes::time"`, suggesting recursion into the debugger hook itself.
I’ve tried things like skipping `Devel::Lite` and `Time::HiRes` calls explicitly, and guarding with `$IN_TRACE`, but the loop persists.
What I’d like to understand is:
1. Why is `DB::sub` being triggered recursively despite the guard?
2. What’s the correct minimal pattern for tracing sub entry/exit safely?
3. Bonus: how best to distinguish user code from CPAN/core subs to keep the trace clean?
Environment:
This is perl 5.38.x built for MSWin32-x64-multi-thread
Running on Windows 10.
Any insight or examples would be appreciated — I’m not trying to build a full debugger, just a simple tracer that logs the call tree.
TIA
PS: So far this has stumped (in no order) ChatGPT, claude, and Gemini.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Trouble writing a simple tracer using the DB package (loops endlessly)
by tonyc (Hermit) on Oct 11, 2025 at 01:45 UTC | |
by clueless newbie (Curate) on Oct 12, 2025 at 19:36 UTC |