Stories
Slash Boxes
Comments

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

schwern (1528)

schwern
  (email not shown publicly)
http://www.pobox.com/~schwern/
AOL IM: Michael Schwern (Add Buddy, Send Message)
Yahoo! ID: schwern (Add User, Send Message)
Jabber: schwern@gmail.com

Schwern can destroy CPAN at his whim.

Journal of schwern (1528)

Friday January 18, 2008
08: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.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.