Module: Bixby::ThreadDump

Defined in:
lib/bixby-common/util/thread_dump.rb

Defined Under Namespace

Classes: LoggerIO

Class Method Summary collapse

Class Method Details

.trap!(logger = nil) ⇒ Thread

Prints a thread dump on ALRM signal kill -ALRM <pid>

You can cancel the signal trap by saving the returned Thread and killing it

Parameters:

  • logger (IO) (defaults to: nil)

    IO-like destination for thread dumps (responds to #puts)

Returns:

  • (Thread)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/bixby-common/util/thread_dump.rb', line 23

def trap!(logger=nil)

  if logger.nil? then
    logger = STDERR
  elsif Module.const_defined?(:Logging) && logger.kind_of?(Logging::Logger) then
    logger = LoggerIO.new(logger)
  end

  t = Bixby::Signal.trap("SIGALRM") do
    write(logger)
  end
  t[:_name] = "dumper [ignore me]"

  logger.puts("Trapping SIGALRM: kill -ALRM #{Process.pid}")
  return t
end

.write(io = STDERR) ⇒ Object

Write thread dump to the given IO-like handle (must respond to #puts)

Parameters:

  • io (IO) (defaults to: STDERR)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/bixby-common/util/thread_dump.rb', line 43

def write(io=STDERR)
  out = []
  out << "=== thread dump for #{$0} (pid=#{Process.pid}): #{Time.now} ==="
  out << ""

  Thread.list.each do |thread|

    # compute thread name, filling in some common libraries
    n = thread.inspect
    if thread.key?(:_name) then
      n += " #{thread[:_name]}"
    else
      t = thread.backtrace.first.strip
      if t =~ %r{rack/handler/puma.rb:.*`join'} then
        n += " puma daemon thread"
      elsif t =~ %r{puma/reactor.rb:.*`select'} then
        n += " puma runloop"
      elsif t =~ %r{puma/server.rb:.*`select'} then
        n += " puma i/o runloop"
      elsif t =~ %r{puma/thread_pool.rb:.*`sleep'} then
        n += " puma threadpool cleanup"
      elsif t =~ %r{lib/eventmachine.rb:.*`run_machine'} then
        n += " EventMachine runloop"
      elsif t =~ %r{celluloid/mailbox.rb:.*`sleep'} then
        n += " celluloid actor thread"
      elsif t =~ %r{bixby-common/util/thread_pool/worker.rb:.*} then
        state = (t =~ /`pop'/ ? "idle" : "busy")
        n += " Bixby::ThreadPool::Worker thread, #{state}"
      end
    end

    out << n
    out << "  " + thread.backtrace.join("\n    \\_ ")
    out << "-"
    out << ""
  end
  out << "=== end thread dump ==="

  io.puts out.join("\n")
end