/usr/lib/ruby/vendor_ruby/celluloid/stack_dump.rb is in ruby-celluloid 0.16.0-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | module Celluloid
class StackDump
module DisplayBacktrace
def display_backtrace(backtrace, output, indent = nil)
backtrace ||= ["EMPTY BACKTRACE"]
backtrace.each do |line|
output << indent if indent
output << "\t" << line << "\n"
end
output << "\n\n"
end
end
class TaskState < Struct.new(:task_class, :type, :meta, :status, :backtrace)
end
class ActorState
include DisplayBacktrace
attr_accessor :name, :id, :cell
attr_accessor :status, :tasks
attr_accessor :backtrace
def dump
string = ""
string << "Celluloid::Actor 0x#{id.to_s(16)}"
string << " [#{name}]" if name
string << "\n"
if cell
string << cell.dump
string << "\n"
end
if status == :idle
string << "State: Idle (waiting for messages)\n"
display_backtrace backtrace, string
else
string << "State: Running (executing tasks)\n"
display_backtrace backtrace, string
string << "\tTasks:\n"
tasks.each_with_index do |task, i|
string << "\t #{i+1}) #{task.task_class}[#{task.type}]: #{task.status}\n"
string << "\t #{task.meta.inspect}\n"
display_backtrace task.backtrace, string, "\t"
end
end
string
end
end
class CellState < Struct.new(:subject_id, :subject_class)
def dump
"Celluloid::Cell 0x#{subject_id.to_s(16)}: #{subject_class}"
end
end
class ThreadState < Struct.new(:thread_id, :backtrace, :role)
include DisplayBacktrace
def dump
string = ""
string << "Thread 0x#{thread_id.to_s(16)} (#{role}):\n"
display_backtrace backtrace, string
string
end
end
attr_accessor :actors, :threads
def initialize(internal_pool)
@internal_pool = internal_pool
@actors = []
@threads = []
snapshot
end
def snapshot
@internal_pool.each do |thread|
if thread.role == :actor
@actors << snapshot_actor(thread.actor) if thread.actor
else
@threads << snapshot_thread(thread)
end
end
end
def snapshot_actor(actor)
state = ActorState.new
state.id = actor.object_id
# TODO: delegate to the behavior
if actor.behavior.is_a?(Cell)
state.cell = snapshot_cell(actor.behavior)
end
tasks = actor.tasks
if tasks.empty?
state.status = :idle
else
state.status = :running
state.tasks = tasks.to_a.map { |t| TaskState.new(t.class, t.type, t.meta, t.status, t.backtrace) }
end
state.backtrace = actor.thread.backtrace if actor.thread
state
end
def snapshot_cell(behavior)
state = CellState.new
state.subject_id = behavior.subject.object_id
state.subject_class = behavior.subject.class
state
end
def snapshot_thread(thread)
ThreadState.new(thread.object_id, thread.backtrace, thread.role)
end
def print(output = STDERR)
@actors.each do |actor|
output.print actor.dump
end
@threads.each do |thread|
output.print thread.dump
end
end
end
end
|