Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

schwern (1528)

  (email not shown publicly)
AOL IM: MichaelSchwern (Add Buddy, Send Message)

Schwern can destroy CPAN at his whim.

Journal of schwern (1528)

Friday January 18, 2008
07:28 PM

Data::Dump::Streamer + $DB::single

[ #35427 ]

I'm trying to track down a nasty problem involving the Class::DBI compatibility wrapper around DBIx::Class and Class::Trigger. I've got closures being created, and then stored somewhere, and then way later in the code those closures run. Oh, and all this is a bug that only happens near the end of a very specific, big wad of code.

Many, many layers, action at a long distance, lots of code to wade through until we hit the problem and those damned opaque closures.

I can't examine what's in the trigger queue because it's all closures, all the debugger or Data::Dumper will show me is "CODE(0x189fc3c)" and maybe line which generated it if I'm lucky. Getting in there with the debugger is a royal pain because every time I have to restart the process, set up the breakpoints... very time consuming and I have to do it over and over again as I slowly zero in on the problem.

There's a little known way to hard code breakpoints into the code. It's done by setting $DB::single. Usually you see it as "$DB::single = 1" but it's even less widely realized that it doesn't have to be 1. You can set it to any true value or expression! "$DB::single = $foo == 42" is "break when $foo is 42". Handy. After a lot of work I finally figured out the particular closure that was misfiring, it was being passed in the wrong arguments. I had to catch the point where that particular closure was being called to see how the arguments were being made. There's hundreds of them, so I can't just go through by hand. How do you identify a particular closure?

Enter Data::Dump::Streamer. By Yves Orton, this is Data::Dumper on steroids. Not satisfied with the limitations of Data::Dumper, Yves improved on it with a module that can serialize most everything you can throw at it. The edge cases most of us consider impossible, like closures. :)

use DDS;  # an alias for Data::Dump::Streamer
my $thing = 42;
my $code = sub { print $thing };
print Dump $code;

my ($thing);
$thing = 42;
$CODE1 = sub {
           print $thing;

Well now, let's combine the two. $DB::single and DDS.

use DDS;
$DB::single = grep /\Q$thing = 42\E/, Dump $code;

Now the code stops right before it runs just the trigger I want.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.