Add remote debugging terminal to mod_perl

jjore on 2009-07-20T15:48:06

Occasionally my mod_perl servers go sour and it's useful to attach a remote debugger. There's typically no useful console and production doesn't run under the debugger. I'm forced into two things: force load the debugger with Enbugger and then have it connect to a remote terminal.

Works great BTW and is almost identical to .http://use.perl.org/user/jjore/journal/39319>. The only real difference is we're eval()ing something different. This is also documented as a "cookbook" recipe in at .
Step 1: Start a remote terminal. I like netcat. I'll just start a Terminal and have it listen on port 8000. Anything that connect there will show up and I'll be able to type to it, etc.

nc -l 8000


Step 2: Attach GDB to mod_perl. Assuming my process ID is 765, I can attach with the simple command:

gdb -p 765


It's occasionally useful to know if there's anything "interesting" going on so get a quick backtrace of the current call stack:

(gdb) backtrace
#0  0xb7f7b919 in poll () from /lib/tls/libc.so.6
#1  0xb7da57ff in apr_poll () from /opt/apache/das/lib/libapr-0.so.0
#2  0x080b2050 in child_main ()
#3  0x080b231e in make_child ()
#4  0x080b2393 in startup_children ()
#5  0x080b279c in ap_mpm_run ()
#6  0x080b93c9 in main ()


Step 3: As in
http://use.perl.org/user/jjore/journal/39319>, I need to know whether there's a thread context to pass into eval().
(gdb) print $thread_context = (void*)Perl_get_context()
$1 = (void *) 0x0


OR

(gdb) print $thread_context = (void*)Perl_get_context()
$1 = (void *) 0x800000


Step 4: Install the debugger. If you've got a $thread_context, it goes before the eval string (eval_pv($ctx,"...",0)).

(gdb) call (void*)Perl_eval_pv("eval { require Enbugger; print STDERR qq{stopping\\n}; $ENV{PERLDB_OPTS} = 'RemotePort=localhost:4000'; Enbugger->stop;}; print STDERR $@; print STDERR qq{stopped?\\n};", 0)


Step 5: profit:

jjore$ nc -l -p 4000

Loading DB routines from perl5db.pl version 1.28 Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

x main::((eval 982):1): print STDERR $@ DB<1> 0 0 DB<1>


Step 6: Now detach to resume your program. You've interrupted your program at two levels. First at perl, so run "c" to continue out from the perl debugger. Second, in gdb so "detach" or "quit" to continue the process.