To trace the execution of a process, gdb needs to
know the PID and the path to the binary that the process is
executing. For Perl code, it's
/usr/bin/perl (or whatever the path to your Perl
is). For httpd processes, it's
the path to your httpd executable—often
the binary is called httpd, but
there's really no standard location for it.
Here are a few examples using gdb. First,
let's go back to our last locking example, execute
it as before, and attach to the process that didn't
get the lock:
panic% gdb /usr/bin/perl 3037
After starting the debugger, we execute the
where command to see the trace:
(gdb) where
#0 0x40209791 in flock ( ) from /lib/libc.so.6
#1 0x400e8dc9 in Perl_pp_flock ( ) at pp_sys.c:2033
#2 0x40099c56 in Perl_runops_debug ( ) at run.c:53
#3 0x4003118c in S_run_body (oldscope=1) at perl.c:1443
#4 0x40030c7e in perl_run (my_perl=0x804bf00) at perl.c:1365
#5 0x804953e in main (argc=3, argv=0xbffffac4, env=0xbffffad4)
at perlmain.c:52
#6 0x4018bcbe in _ _libc_start_main ( ) from /lib/libc.so.6
That's not what we may have expected to see (i.e., a
Perl stack trace). And now it's a different trace
from the one we saw when we were using strace.
Here we see the current state of the call stack, with main(
) at the bottom of the stack and flock(
) at the top.
We have to find out the place the code was called
from—it's possible that the code calls
flock( ) in several places, and we
won't be able to locate the place in the code where
the actual problem occurs without having this information. Therefore,
we again use the curinfo macro after loading it
from the .gdbinit file:
(gdb) source /usr/src/httpd_perl/mod_perl-1.25/.gdbinit
(gdb) curinfo
9:/home/httpd/perl/excl_lock.pl
As we can see, the program was stuck at line 9 of
/home/httpd/perl/excl_lock.pl and
that's the place to look at to resolve the problem.
When you attach to a running process with gdb, the
program stops executing and control of the program is passed to the
debugger. You can continue the normal program run with the
continue command or execute it step by step with
the next and step commands,
which you type at the gdb prompt.
(next steps over any function calls in the
source, while step steps into them.)
The use of C/C++ debuggers is a large topic, beyond the scope of this
book. The gdb man and info pages are quite good.
You might also want to check ddd (the Data Display
Debugger), which provides a visual interface to
gdb and other debuggers. It even knows how to
debug Perl programs.
For completeness, let's see the
gdb trace of the httpd
process that's hanging in the
while(1) loop of the first example in this
section:
panic% gdb /home/httpd/httpd_perl/bin/httpd 1005
(gdb) where
#0 0x402251c1 in nanosleep ( ) from /lib/libc.so.6
#1 0x40225158 in sleep ( ) from /lib/libc.so.6
#2 0x4014d3a6 in Perl_pp_sleep ( ) at pp_sys.c:4187
#3 0x400f5c56 in Perl_runops_debug ( ) at run.c:53
#4 0x4008e088 in S_call_body (myop=0xbffff688, is_eval=0) at perl.c:1796
#5 0x4008dc4f in perl_call_sv (sv=0x82fc75c, flags=4) at perl.c:1714
#6 0x807350e in perl_call_handler (sv=0x82fc75c, r=0x8309eec, args=0x0)
at mod_perl.c:1677
#7 0x80729cd in perl_run_stacked_handlers (hook=0x80d0db9 "PerlHandler",
r=0x8309eec, handlers=0x82e9b64) at mod_perl.c:1396
#8 0x80701b4 in perl_handler (r=0x8309eec) at mod_perl.c:922
#9 0x809f409 in ap_invoke_handler (r=0x8309eec) at http_config.c:517
#10 0x80b3e8f in process_request_internal (r=0x8309eec) at http_request.c:1286
#11 0x80b3efa in ap_process_request (r=0x8309eec) at http_request.c:1302
#12 0x80aae60 in child_main (child_num_arg=0) at http_main.c:4205
#13 0x80ab0e8 in make_child (s=0x80eea54, slot=0, now=981621024)
at http_main.c:4364
#14 0x80ab19c in startup_children (number_to_start=3) at http_main.c:4391
#15 0x80ab80c in standalone_main (argc=1, argv=0xbffff9e4) at http_main.c:4679
#16 0x80ac03c in main (argc=1, argv=0xbffff9e4) at http_main.c:5006
#17 0x401bbcbe in _ _libc_start_main ( ) from /lib/libc.so.6
As before, we can see a complete trace of the last executed call. To
see the line the program hangs, we use curinfo
again:
(gdb) source /usr/src/httpd_perl/mod_perl-1.25/.gdbinit
(gdb) curinfo
9:/home/httpd/perl/hangme.pl
Indeed, the program spends most of its time at line 9:
7 : while (1) {
8 : $i++;
9 : sleep 1;
10: }