Ruby monitor segmentation fault

monitorruby

I followed the example from http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/index.html and modified the code a bit:

require 'monitor.rb'

buf = []
buf.extend(MonitorMixin)
empty_cond = buf.new_cond

producer = Thread.start do
# producer
line = "produce at #{Time.now}"
#while line
  buf.synchronize do
    puts "==> #{line}"
    buf.push(line)
    empty_cond.signal
  end
  sleep(2)
  #line = "produce at #{Time.now}"
#end
end

loop do
   buf.synchronize do
      empty_cond.wait_while { buf.empty? }
      item = buf.shift
      puts "got #{item.inspect}"
   end
end

I let the program run. Around 5 min later, it throws a "Segmentation fault". Something related to a deadlock?

/Jack

Best Answer

As your code stands (with the commented out while-statement in producer-loop) the producer thread simply runs through the loop once and exits. The consumer reads the one produced line from buf and then is left in a deadlock waiting for more lines that will never arrive.

Ruby's Thread scheduler has inbuilt deadlock-detection, so it will terminate the program when it sees that the 'consumer'-loop has deadlocked.

To see the deadlock for yourself, turn the producer into a global variable $producer and wrap the loop-statement with $consumer = Thread.start do ... end. Loading the code into irb and evaluating $producer should result in => #< Thread:0x000000010afb58 dead > (and $consumer in a sleeping thread)

Take out the comments relating to producer's while-loop and you'll have a working (infinite) loop that produces the current time at 2 second intervals.