- Do you have (server) processes that sometimes crash for mysterious reasons?
- Can you not figure out why?
- Do they not print any error messages to their log files upon crashing?
- Are debuggers complicated, scary things that you'd rather avoid?
crash-watch to the rescue! This little program will monitor a specified process and wait until it crashes. It will then print useful information such as its exit status, what signal caused it to abort, and its backtrace.
Installation with RubyGems
gem install crash-watch
You must also have GDB installed. macOS already has it by default. If you're on Linux, try one of these:
apt-get install gdb yum install gdb
$ crash-watch <PID> Monitoring PID <PID>... (...some time later, <PID> exits...) Process exited. Exit code: 0 Backtrace: Thread 1 (process 95205): #0 0x00007fff87ea1db0 in _exit () No symbol table info available. #1 0x000000010002a260 in ruby_stop () No symbol table info available. #2 0x0000000100031a54 in ruby_run () No symbol table info available. #3 0x00000001000009e4 in main () No symbol table info available.
While monitoring the process, you may interrupt
crash-watch by pressing Ctrl-C.
crash-watch will then detach from the process, which will then continue normally. You may re-attach
crash-watch --help for more usage options.
Dumping live backtrace
Instead of waiting until a process crashes, you can also dump a live backtrace of a process.
crash-watch will immediately exit after dumping the backtrace, letting the process continue as normally.
$ crash-watch --dump <PID> Current thread (1) backtrace: #0 0x00007fff81fd9464 in read () No symbol table info available. #1 0x0000000100060d3e in ?? () No symbol table info available.
Goodie: GDB controller
I've written a small library for controlling gdb, which
crash-watch uses internally. With CrashWatch::GdbController you can send arbitrary commands to gdb and also get its response.
require 'crash_watch/gdb_controller' gdb = CrashWatch::GdbController.new
This will spawn a new GDB process. Use
#execute to execute arbitrary GDB commands. Whatever the command prints to stdout and stderr will be available in the result string.
gdb.execute("bt") # => backtrace string gdb.execute("p 1 + 2") # => "$1 = 3\n"
#close when you no longer need it.