thread_deadlock_error_test.rb

Test code to show how this error occurs - nhm tanveeer hossain khan, 04/30/2013 12:12 AM

Download (1.47 KB)

 
1
require 'minitest/autorun'
2

    
3
class ThreadPool
4
  attr_accessor :size, :threads, :jobs
5

    
6
  def initialize(size)
7
    @size    = size
8
    @jobs    = Queue.new
9
    @threads = create_threads
10
  end
11

    
12
  def create_threads
13
    @size.times.map do |i|
14
      Thread.start do
15
        Thread.current[:id] = i
16

    
17
        catch(:thread_quit) do
18
          loop do
19
            job, args = @jobs.pop
20
            job.call *args
21
          end
22
        end
23
      end
24
    end
25
  end
26

    
27
  def join
28
    threads.each &:join
29
  end
30

    
31
  def shutdown
32
    size.times do
33
      add { throw :thread_quit }
34
    end
35

    
36
    threads.map &:join
37
  end
38

    
39
  def add(*args, &job)
40
    jobs << [job, args]
41
  end
42

    
43
  def queue_size;
44
    jobs.size
45
  end
46
end
47

    
48
describe ThreadPool do
49
  before do
50
    @pool = ThreadPool.new 2
51
    @pool.extend MiniTest::Expectations
52
  end
53

    
54
  it 'generates "No live threads left. Deadlock?deadlock?"' do
55
    100.times do |i|
56
      @pool.add(i) do |i|
57
        puts "doing (#{i + 1})..."
58
        sleep 0.01
59
      end
60
    end
61

    
62
    begin
63
      @pool.join
64
    rescue Exception => e
65
      assert_equal 'No live threads left. Deadlock?', e.message
66
    end
67
  end
68

    
69
  it 'works with workaround' do
70
    100.times do |i|
71
      @pool.add(i) do |i|
72
        puts "doing (#{i + 1})..."
73
        sleep 0.01
74
      end
75
    end
76

    
77
    exception = nil
78

    
79
    begin
80
      Thread.start do
81
        break until @pool.threads.select(&:alive?).size.zero?
82
      end.join
83
      sleep 1
84
    rescue Exception => e
85
      exception = e
86
    end
87

    
88
    assert_nil exception
89
  end
90
end