sigdump

Server applications (like Rails app) cause performance problems, deadlock or memory swapping from time to time. But it's painful to reproduce such kind of problems. If we can get information from a running process without restarting it, it's really helpful.

sigdump gem installs a signal handler which dumps backtrace of running threads and number of allocated objects per class.

If GC profiler is enabled (GC::Profiler.enable is called), it also dumps GC statistics.

Install

Just install one gem sigdump and require sigdump/setup:

gem 'sigdump', :require => 'sigdump/setup'

Usage

Send SIGCONT signal to dump backtrace and heap status to /tmp/sigdump-<pid>.log:

$ kill -CONT <pid>

Set SIGDUMP_SIGNAL environment variable to change the signal (default: SIGCONT).

Set SIGDUMP_PATH environment variable to change the output path (default: /tmp/sigdump-<pid>.log). You can set "-" here to dump to STDOUT, "+" to dump to STDERR.

Sample outout

$ cat /tmp/sigdump-9218.log
Sigdump at 2013-04-24 16:57:12 +0000 process 9218 (unicorn worker[3] -E staging -c /etc/unicorn/staging.rb -E staging)
  Thread #<Thread:0x00000001424518> status=run priority=0
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:32:in `dump_backtrace'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:19:in `block in dump_all_thread_backtrace'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:18:in `each'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:18:in `dump_all_thread_backtrace'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:9:in `block (2 levels) in install_thread_dump_handler'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:91:in `open'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:91:in `_open_dump_path'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/sigdump-0.1.0/lib/sigdump.rb:7:in `block in install_thread_dump_handler'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/http_server.rb:626:in `call'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/http_server.rb:626:in `select'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/http_server.rb:626:in `worker_loop'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/http_server.rb:487:in `spawn_missing_workers'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/http_server.rb:137:in `start'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/gems/unicorn-4.3.1/bin/unicorn:121:in `<top (required)>'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/bin/unicorn:23:in `load'
      /srv/staging/current/vendor/bundle/ruby/1.9.1/bin/unicorn:23:in `<main>'
  Built-in objects:
   367,492: TOTAL
   208,193: T_STRING
    61,817: T_ARRAY
    37,343: T_DATA
    28,293: T_NODE
    10,678: T_OBJECT
     6,385: T_HASH
     5,957: T_CLASS
     2,300: T_ICLASS
     2,184: T_REGEXP
     1,547: T_MODULE
       900: T_FLOAT
       677: T_STRUCT
       497: T_BIGNUM
       432: T_MATCH
       251: T_RATIONAL
        29: T_FILE
         8: FREE
         1: T_COMPLEX
  All objects:
   207,335: String
    32,987: Array
    28,665: RubyVM::InstructionSequence
     5,863: Hash
     3,759: RubyVM::Env
     3,680: Proc
     2,338: Class
     2,184: Regexp
     1,632: MIME::Type
     1,547: Module
     1,040: Gem::Version
       982: Gem::Requirement
       945: Float
       920: Journey::Nodes::Cat
       804: Time
       660: Gem::Dependency
       497: Bignum
  ...
  String 7,556,137 bytes
   Array 821 elements
    Hash 90 pairs