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
|
module Specs
class << self
def loose_threads
Thread.list.map do |thread|
next unless thread
next if thread == Thread.current
if RUBY_PLATFORM == "java"
# Avoid disrupting jRuby's "fiber" threads.
name = thread.to_java.getNativeThread.get_name
next if /Fiber/ =~ name
next unless /^Ruby-/ =~ name
backtrace = thread.backtrace # avoid race maybe
next unless backtrace
next if backtrace.empty? # possibly a timer thread
else
# Sometimes stays
next if thread.backtrace.nil?
next unless thread.backtrace.is_a?(Array)
next if thread.backtrace.empty?
next if thread.backtrace.first =~ /timeout\.rb/
end
thread
end.compact
end
def thread_name(thread)
RUBY_PLATFORM == "java" ? thread.to_java.getNativeThread.get_name : ""
end
def assert_no_loose_threads!(location)
loose = Specs.loose_threads
backtraces = loose.map do |thread|
name = thread_name(thread)
description = "#{thread.inspect}#{name.empty? ? '' : "(#{name})"}"
"Runaway thread: ================ #{description}\n" \
"Backtrace: \n ** #{thread.backtrace * "\n ** "}\n"
end
return if loose.empty?
if RUBY_PLATFORM == "java" && !Nenv.ci?
STDERR.puts "Aborted due to runaway threads (#{location})\n"\
"List: (#{loose.map(&:inspect)})\n:#{backtraces.join("\n")}"
STDERR.puts "Sleeping so you can investigate on the Java side...."
sleep
end
raise Celluloid::ThreadLeak, "Aborted due to runaway threads (#{location})\n"\
"List: (#{loose.map(&:inspect)})\n:#{backtraces.join("\n")}"
end
end
end
|