Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Modifying SelfLoader to save eval() text

by rockyb (Scribe)
on Jun 07, 2013 at 17:13 UTC ( #1037710=perlquestion: print w/replies, xml ) Need Help??
rockyb has asked for the wisdom of the Perl Monks concerning the following question:

I noticed the following problem in using the perl debugger, Devel::Trepan, with code that uses the SelfLoader perl module.

SelfLoader uses eval() to install subroutines at run time. The perl debugger would like to have access to the text of the eval string. With this, when one is debugging into one of those procedures the debugger can show you were you are. The two things that defeat this in SelfLoader is the use of lexically-scoped (or my) hash %Cache of such added text which it deletes just before running the code.

The general outline of the SelfLoader is:

package SelfLoader; ... my %Cache; # private cache for all SelfLoader's client packages ... AUTOLOAD { our $AUTOLOAD; # $AUTOLOAD is fully-qualified function name, e.g. MyPackage::fn ... # set $Cache{$AUTOLOAD} to file text from __DATA__ to __END__ ... delete $Cache{$AUTOLOAD}; goto &$AUTOLOAD; }

So basically, when debugging I'd like to rewrite the above to change my %Cache to our %Cache and remove the delete $Cache{$AUTOLOAD};

Alternatively, the routine that updates %Cache is called SelfLoader::_add_to_cache() so that could be augmented to save to another hash somewhere. But the problem here is that it still needs to update the lexically-scoped %Cached hash.

The two techniques that come to mind are monkey-patching and the Decorator pattern. Alas, because of the specifics of how SelfLoader works which I won't go into here (and am not totally positive I understand), I don't see how to do either.

Thoughts on how to address? Thanks.

Replies are listed 'Best First'.
Re: Modifying SelfLoader to save eval() text
by rockyb (Scribe) on Jun 08, 2013 at 11:00 UTC

    Lacking other suggestions, here is something that almost works and that is described below. But now the problem devolves into being able to overwrite or chain after SelfLoader::AUTOLOAD if SelfLoader is use'd.

    Alternatively if I could trap, replace, or chain on a use SelfLoader that would work too.

    I've written a replacement for SelfLoader called Devel::Trepan::SelfLoader and this can be distributed with Devel::Trepan.

    The problem I encounter is that the debugger can be and often is loaded before the program to be debugged. So when the debugged program issues a use SelfLoader any AUTOLOAD or SelfLoader::AUTOLOAD code that I've written gets redefined. It looks like AUTOLOAD isn't chained by default, but instead the last one defined is used.

      With Devel::Trepan commit 263c7bfce0 I now have everything solved. There could be a better solution, but this one has certain advantages.

      I can now use the debugger to fully debug a little selfloader Perl script. Since the debugger has the text of the eval string now, it writes out a temporary file. You can now list the code or set line number breakpoints in it.

      The last missing problem was making sure we hooked into a debugger-enabled version of SelfLoader rather than the one that comes with Perl. In order to do this, I now trap on use statements by inserting a code reference at the beginning of %INC. See the documentation on perldoc on require and how it uses %INC.

      Specifically, my code returns a file-handle glob for my debugger-enabled SelfLoader when I see that is requested. It has to be a real glob rather than a scalar reference to a file handle, or else the lookup tacitly fails.

      With this custom program added to %INC I can also do other cool things. Like trace or perhaps debug into use code!

      So in closing, I'll say that I am amazed at how flexible Perl is. There are lots and lots of mechanisms there. But I am equally amazed at how difficult it is to provide good debugging facility. I think most people just live with things like not being able to list lines of selfloader code or other kinds of eval'd code. Probably many (like myself too often) have to rely on just print statements.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1037710]
Front-paged by Arunbear
[erix]: haha

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2018-06-22 17:21 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (124 votes). Check out past polls.