Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Trying to track a sleeping CGI request with gdb

by talexb (Canon)
on Oct 10, 2006 at 16:47 UTC ( #577445=perlquestion: print w/ replies, xml ) Need Help??
talexb has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to understand why a Perl CGI that's the most used page in my web application appears to sometimes 'go to sleep', tying up an Apache kid or two, when all other web pages run fine.

This is more or less a regular CRUD or BREAD web application running through mod_cgi, not mod_perl, using Apache 1.3, Perl 5.8.0, accessing a Postgresql database. While the database has been suspect before, it doesn't appear to be the root of the problem this time around, since I'm not seeing the fatal error about the number of connections being exceeded, and I don't see any pending SELECT statements.

After all that preamble, here's my question: I'd like to try to run gdb against the 'awake but not running and not a zombie' process to find out where it's at, but I'm not familiar about how to do such a thing. The man page suggests I should be able to use

gdb program 1234
to debug a running process .. in the case of a CGI, I presume that would be something like
gdb '/usr/bin/perl /path/to/cgi-bin/script.cgi' 1234
where 1234 was the PID of the sleepy child. Since the problem has solved itself for now, I can't try it today, but I'd like to know for the future, so I can found out what the heck is going on.

I welcome your suggestions. (No, there's nothing useful in neither the log file nor the Log::Log4perl debug logs .. it just goes to TT2's process method and never comes back.)

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Comment on Trying to track a sleeping CGI request with gdb
Select or Download Code
Re: Trying to track a sleeping CGI request with gdb
by jbert (Priest) on Oct 10, 2006 at 17:54 UTC
    If your OS has 'pstack' (which at least Linux and Solaris do) then you can get a stack trace from a running process without using gdb.

    You won't see too much of use unless you've got symbols loaded, but it's worth a try.

    Otherwise, on Linux you can try 'strace -p <pid>' to get a look at what system calls the process is doing, this can be quite illuminating.

    The equivalent on Solaris is 'truss', which can also peek into shared libraries (see the -u option).

      strace! That's the sucker.

      Just tried it on another process (not the one I want) but at least it gave me a C style trace of what's going on, and that should be enough to find out where the code's at and what it's waiting for.

      Alex / talexb / Toronto

      "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Trying to track a sleeping CGI request with gdb
by ikegami (Pope) on Oct 10, 2006 at 18:04 UTC

    Not knowing gdb, that should surely be

    gdb /usr/bin/perl /path/to/cgi-bin/script.cgi 1234

    Remember, perl is the executable. The script name and arguments for the script are arguments to perl.

    ( I thought 1234 was for the perl script, not for gdb, so I extrapolated incorrectly. )

      Yes, but gdb expects after the program name, a core dump file, or a pid.

      So to pass arguments to the executable, you need to run it from within gdb as such:

      $ gdb /usr/bin/perl ... .. (gdb) run /path/to/cgi-bin/script.cgi

      He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.
      Chady | http://chady.net/
      Are you a Linux user in Lebanon? join the Lebanese GNU/Linux User Group.
        "--args" gdb option allows to pass arguments to the executable given a program X and list of parameters a b c: %gdb --args X a b c
Re: Trying to track a sleeping CGI request with gdb
by sgifford (Prior) on Oct 10, 2006 at 18:21 UTC
    As far as the OS is concerned, the running program is perl, and your script is just an argument to it. So you would do:
    gdb /usr/bin/perl 1234
    

    But this is doing to drop you into the middle of a running perl process, and you may not find that very helpful. It's easy enough to write a test script that will sleep for long enough that you can attach to it and poke around in the debugger. That should give you an idea of how to get around in the debugger, and whether or not you'll find this useful.

    Ideally, you would want to drop into perl -d, but that currently isn't possible; see How to attach a perl debugger to a running perl.

    I usually debug these sorts of things by printing out a lot of debugging information. Then when it's stuck, you can see the last thing it printed out to figure out what it's doing. As others have mentioned, strace/truss can also be very useful.

Re: Trying to track a sleeping CGI request with gdb
by Anonymous Monk on Oct 10, 2006 at 20:00 UTC
    Also, might want to upgrade Perl. Version 5.8.0 had a lot of odd bugs.
Re: Trying to track a sleeping CGI request with gdb
by shmem (Canon) on Oct 10, 2006 at 22:58 UTC
    It might be overkill to use gdb for debugging a script. After all, you aren't debugging perl yet, are you? You could try to force the script to tell you where it got stuck via alarm:
    #!/usr/bin/perl -w use strict; use Carp; $SIG{'ALRM'} = \&debug; alarm 5; sleep 1; sleep 1; sleep 1; sleep 1; sleep 1; sleep 1; sleep 1; sub debug { confess "here I got stuck:"; exit 1; } __END__ here I got stuck: at alarm.pl line 17 main::debug('ALRM') called at alarm.pl line 13 eval {...} called at alarm.pl line 13

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Trying to track a sleeping CGI request with gdb
by sfink (Deacon) on Oct 12, 2006 at 04:12 UTC
    With my version of gdb, that would be gdb -p 1234.

    When doing this, it is often useful to ask Perl to tell you where it is. For that, I do p Perl_warner(my_perl, 1, "oops"), which will print out something like "oops at Snorkus.pm line 56".

    That may require debug symbols. You can install the perl-debuginfo RPM if you can find it. (I got it via rpmbuild --rebuild perl-*.src.rpm)

    Or you could do something like p Perl_eval_pv(my_perl, "use Carp; Carp::cluck('oops')", 0) to get a full stack trace.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://577445]
Approved by Joost
Front-paged by andyford
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2014-11-25 00:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (148 votes), past polls