Home arrow Perl Programming arrow Page 3 - Debugging Perl

Doing Whatever I Want - Perl

Every developer knows that debugging is one of the most important parts of coding. This two-part article focuses on Perl debuggers. It is excerpted from chapter four of Mastering Perl, written by Brian D Foy (O'Reilly; ISBN: 0596527241). Copyright © 2007 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

TABLE OF CONTENTS:
  1. Debugging Perl
  2. The Best Debugger in the World
  3. Doing Whatever I Want
  4. Program Tracing
  5. Safely Changing Modules
By: O'Reilly Media
Rating: starstarstarstarstar / 2
July 24, 2008

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

I can change the warn and die functions myself by messing with %SIG. I like to use these to peer into code Iím trying to figure out, but I donít use these to add features to code. Itís just part of my debugging toolbox.

The pseudokeys __WARN__ and __DIE__ hold the functions that perform those actions when I use the warn or die functions. I can use a reference to a named subroutine or an anonymous subroutine:

  $SIG{__DIE__} = \&my_die_handler;
  $SIG{__DIE__} = sub { print "I'm about to die!" )

Without going through the entire code base, I can change all of the die calls into the more informative croak calls.ß In this example, I preface the subroutine call with an & and no parentheses to trigger Perlís feature to pass on the current argument list to the next subroutine call so croak gets all of the arguments I pass:

  use Carp;
  $SIG{__DIE__} = sub { &Carp::croak };

  die "I'm going now!"; # really calls croak now

If I only want to do this for part of the code, I can use local (since %SIG is a special variable always in main::). My redefinition stays in effect until the end of the scope:

  local $SIG{__DIE__} = sub { &Carp::croak };

After either of my customized routines runs, the functions do what they would otherwise do; warn lets the program continue, and die continues its exception processing and eventually stops the program.

Since croak reports each level of the call stack and I called it from an anonymous subroutine, I get an artifact in my output:

  use Carp;

  print "Starting program...\n";

  $SIG{__DIE__} = sub {
          local $Carp::CarpLevel = 0;

          &Carp::croak;
          };

  foo(); # program dies here

  sub foo { bar() }

  sub bar { die "Dying from bar!\n"; }

In the stack trace, I see a subroutine call from __ANON__ followed by the subroutine calls I expect to bar() and foo():

  Starting program...
  Dying from bar!
  
at die.pl line 12
                 main::__ANON__('Dying from bar!\x{a}') called at die.pl line 20
                 main::bar() called at die.pl line 18
                 main::foo() called at die.pl line 16

I change my anonymous subroutine to adjust the position in the stack where croak starts its report. I set the value of $Carp::CarpLevel to the number of levels I want to skip, in this case just 1:

  $SIG{__DIE__} = sub {
          local $Carp::CarpLevel = 1;

          &Carp::croak;
          };

Now I donít see the unwanted output:

  Starting program...
  Dying from bar!
  
at die.pl line 12
                  main::bar() called at die.pl line 18
                  main::foo() called at die.pl line 16

For a real-life example of this in action, check out the CGI::Carp module. Lincoln Stein uses the %SIG tricks to redefine warn and die in a web-friendly way. Instead of an annoying ďServer Error 500Ē message, I can get useful error output by simply loading the module. While loading, CGI::Carp sets $SIG{__WARN__} and $SIG{__DIE__}:

  use CGI::Carp qw(fatalsToBrowser);

The fatalsToBrowser function takes over the resulting page to show me the error, but the module has other interesting functions such as set_message, which can catch compile-time errors and warningsToBrowser, which makes the warnings in HTML comments embedded in the output.

Of course, I donít recommend that you use this in production code. I donít want users to see the programís errors. They can be handy when I have to debug a program on a remote server, but once I figure out the problem, I donít need it anymore. By leaving it in there I let the public figure out how Iím doing things, and thatís bad for security.



 
 
>>> More Perl Programming Articles          >>> More By O'Reilly Media
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PERL PROGRAMMING ARTICLES

- Perl Turns 25
- Lists and Arguments in Perl
- Variables and Arguments in Perl
- Understanding Scope and Packages in Perl
- Arguments and Return Values in Perl
- Invoking Perl Subroutines and Functions
- Subroutines and Functions in Perl
- Perl Basics: Writing and Debugging Programs
- Structure and Statements in Perl
- First Steps in Perl
- Completing Regular Expression Basics
- Modifiers, Boundaries, and Regular Expressio...
- Quantifiers and Other Regular Expression Bas...
- Parsing and Regular Expression Basics
- Hash Functions

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: