jmo has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I'm adding a debug function to a central module in a perl project. The plan is to listen to SIGUSR1 and if receiving it dump a lot of useful info to a file.


The signal handling isn't a problem but I'm not sure how to go about with dumping the data. What I'd really want put out is:
1. All global variables in the starting script
2. The local variables of the function it got interrupted from
3. Where in the code the script currently is

3 is very straight forward with caller() and my hope is to use %:: for 1 and 2. Unfortunately I've got some problem with them, for 1 I don't know how to know what type it is (hash,scalar, array, code...), or rather I thought I knew by doing:
foreach my $entry (sort values %:: ) { print "*" x 10, "Name: $entry Type: "; print "scalar is defined\t" if defined ${$entry}; print "array is defined\t" if defined @{$entry}; print "hash is defined\t" if defined %{$entry}; print "sub is defined\t" if defined &{$entry}; print "\n"; }
This one misses variables though which really confuses me.
So I suppose my questions are:
1. How do I reliably list and print all globally declared variables in the main:: name space?
2. Is it at all possible to access the local variables of a subroutine which is currently running? (I mean the variables of the subroutine which was executing when the script got the signal)
3. If 2 is possible, can I trace upwards and get the variables for subroutines calling the "active" subroutine?

I've read through Mastering perl chap 8, perlvar, perlmod and perlref but I don't see much in traversing the symbol table.
Using CPAN modules is unfortunately not an option due to access restrictions in the target environment so I'll be forced to reinvent wheels if need be.
The small isolated code I currently have is:
use strict; use sig_bla; sub bar { my $foo = 5; open (FO, ">/tmp/test_file") or die "doh!?"; print "file open\n"; print FO "Some small data in the open file\n"; while (1) { sleep 1; } } our @MYARR = ( 1, 2 ,3); my @my_arr = ( 1, 2 ,3); my $apa = 2; my $FOO = 10; our %MY_HASH = ( a => 2, b => 5); my %myhash = ( a => 2, b => 5); print "$$\n"; &bar();
and
package sig_bla; use strict; use Data::Dumper; $SIG{USR1} = \&handle; sub handle { print "Got sig\n"; for (0..5) { my (@ap) = caller ($_); last unless scalar @ap; print Dumper \@ap; } foreach my $entry (sort values %:: ) { print "*" x 10, "Name: $entry Type: "; print "scalar is defined\t" if defined ${$entry}; print "array is defined\t" if defined @{$entry}; print "hash is defined\t" if defined %{$entry}; print "sub is defined\t" if defined &{$entry}; print "\n"; } } 1;
Thanks in advance

Replies are listed 'Best First'.
Re: Dumping the content of a module
by cdarke (Prior) on Feb 18, 2011 at 13:24 UTC
    %:: gives the stash of package variables, lexical ('my') variables are held on a PAD. They can be listed using B::Showlex, which is a base module. You can call it at runtime like this:
    use strict; use warnings; use B::Showlex; sub dumpit { B::Showlex::compile(-newlex,-nosp,'mysub')->() } sub mysub { my $subvar = 42; my @subvar = qw(The quick brown fox); my %subvar = qw(red live blue neutral green earth); return; } dumpit();
    Which gives:
    main::mysub: main::mysub Pad has 17 entries 1: PVNV (0x1b49b24) "$subvar" = NULL (0x1b49b44) 2: PVNV (0x1b49ab4) "@subvar" = AV (0x1b49a74) undef 4: PVNV (0x1b49a44) "%subvar" = HV (0x1b49a24) HASH
    Update: B::Showlex writes to STDOUT, you can redirect it to a string then extract the variable names:
    sub dumpit { my $out; # Redirect STDOUT to a string open my $oldout, ">&STDOUT" or warn "Can't dup STDOUT: $!"; close STDOUT; open(STDOUT,'>',\$out) or warn "STDOUT redirection failed:$!"; B::Showlex::compile(-newlex,-nosp,'mysub')->(); my @lines = split(/\n/,$out); shift @lines; shift @lines; for my $line (@lines) { $line =~ s/.*\"(.\w+)\".*/$1/; print STDERR "$line\n"; } # Restore STDOUT open STDOUT, ">&", $oldout or die "Can't dup \$oldout: $!"; }
    Update to update: saved and restored STDOUT.
Re: Dumping the content of a module
by ig (Vicar) on Feb 20, 2011 at 18:52 UTC