Sample Debug Session Using The Perl Debugger
Catalyst's logging and debug output options usually give enough information to work out what is going wrong with your application. When they don't, you can use the perl debugger on script/myapp_server.pl (or similar) to step through the code manually, inspect the data and see what is happening.
What follows is an example of debugging a problem with Parley 0.07 that turned out to be an issue with DBIx::Class::Loader 0.10.
Start the debugger
# cd /var/www/catalyst/parley # perl -d script/parley_server.pl -k
-k is needed to make Internet Explorer redirects work.
main::(script/parley_server.pl:14): 14: my $debug = 0;
Type 'c'ontinue and press RETURN
DB<1> c lots of messages from Catalyst
Browse to http://myserver:3000 and use the application. Try posting on the bulletin board screen and it fails. The debugger shows a full perl call stack on screen and you can see it fails in thread/view. The error message seems to indicate a prior db add failure, so that's where to look.
Add a breakpoint to parley's _add_new_topic() by editing /lib/Parley/Controller/Thread.pm and at line 137 adding
$DB::single = 1;
just before the eval block where the new thread and post are created.
Now quit out of the debugger with 'q'uit then restart it to pick up the changed code.
<CTRL-C> DB<25> q # perl -d script/parley_server.pl -k
Back to the browser and try posting again on the add bulletin board screen.
This time it breaks out to the debugger in _add_new_topic() and you can use 'n'ext to step over subroutine calls
DB<5> n
until the $self->_update_last_post() line then 's'tep into the subroutine and walk through the code.
DB<25> s
That goes through the following:
DBIx::Class::AccessGroup anonymous function DBIx::Class::Row::get_column() DBIx::Class::Relationship::Accessor anonymous function DBIx::Class::Relationship::Base::set_from_related()
I type in 'v'iew to see where I am:
316: my ($self, $rel, $f_obj) = @_;
DB<1> v
313 314
315 sub set_from_related {
316==> my ($self, $rel, $f_obj) = @_;
317: my $rel_obj = $self->_relationships->{$rel};
318: $self->throw( "No such relationship ${rel}" ) unless $rel_obj;
319: my $cond = $rel_obj->{cond};
320: $self->throw( "set_from_related can only handle a hash condition; the "
321 ."condition for $rel is of type ".(ref $cond ? ref $cond : 'plain scalar'))
322 unless ref $cond eq 'HASH';
I want to see a few more code lines so use 'l'ist:
DB<2> l
323: my $f_class = $self->resolve_class($rel_obj->{class});
324: $self->throw( "Object $f_obj isn't a ".$f_class )
325 unless $f_obj->isa($f_class);
326: foreach my $key (keys %$cond) {
327: next if ref $cond->{$key}; # Skip literals and complex conditions
328: $self->throw("set_from_related can't handle $key as key")
329 unless $key =~ m/^foreign\.([^\.]+)$/;
330: my $val = $f_obj->get_column($1);
331: $self->throw("set_from_related can't handle ".$cond->{$key}." as value")
332 unless $cond->{$key} =~ m/^self\.([^\.]+)$/;
Then I look at the params with e'x'amine:
DB<1> x @_
0 Parley::Model::ParleyDB::Thread=HASH(0xbb9f0ac)
'_column_data' => HASH(0xb55cde0)
'active' => 1
'created' => '2006-01-16 18:50:21.761284+00'
'creator' => 1
'forum' => 0
'last_post' => undef
'post_count' => 0
'subject' => 'a2'
'thread_id' => 20
'view_count' => 0
'_in_storage' => 1
'_relationship_data' => HASH(0xbb9eec0)
'forum' => Parley::Model::ParleyDB::Forum=HASH(0xbb9efbc)
'_column_data' => HASH(0xbb9a738)
'active' => 1
'description' => 'General off-topic discussion'
'forum_id' => 0
'last_post' => 20
'name' => 'Off-Topic'
'post_count' => 0
'_dirty_columns' => HASH(0xbba55b4)
'last_post' => 1
'_in_storage' => 1
'_inflated_column' => HASH(0xbba5470)
empty hash
1 'last_post'
2 20
And that value of 20 in param 2 is what will cause a throw() at line 325 because it's a scalar and not an object, so $f_obj->isa($f_class) is false and an exception is thrown.
The solution in this case meant contacting the module authors who investigated, found and corrected a bug.
For more information type
# perldoc perldebug
and read this article Using the Perl Debugger by Brian D. Foy.
Peter Edwards <peterdragon@users.sourceforge.net>
Emacs and cperl-mode users should know about cperl-db. In my installation of this (os x), I have two issues. First, I have to manually modify the command that cperl-mode suggests, changing "perl" to "perl -d" (this may be an aquaemacs/os x issue), and I also have to ensure that any paths to files in the application I am debugging are absolute not relative paths. Both issues have work arounds, and are almost certainly easily fixable. - kd
See Also
Testing for information about using test harnesses. The combination of Test Harness, and interactive debugger is very powerful.
