forkbreak / fork_break

Fork with breakpoints, for testing multiprocess behaviour.
MIT License
61 stars 6 forks source link

Problem with mutexes #3

Closed calonso closed 11 years ago

calonso commented 11 years ago

Hi.

I'm facing problems when trying to test concurrency with mutexes involved. I don't know if is my fault or some kind of bug, but I really need help.

In my model

class A < ActiveRecord::Base
  class_attribute :mutex
  self.mutex ||= Mutex.new

  def model_method
    puts 'try'
    A.mutex.lock
    puts 'inside'
      ...
    A.mutex.unlock
    puts 'outside'
  end
end

In my rspec

p1, p2 = 2.times.map do 
  ForkBreak::Process.new do |bps|
    ActiveRecord::Base.connection.reconnect!
    obj = A.new
    original = obj.method(:model_method)
    A.any_instance.stub(:model_method) do |*args|
      original.call(*args)
      bps << :after_method
    end

    obj.model_method
  end
  p1.run_until(:after_method).wait
  p2.run_until(:after_method).wait

  p1.finish.wait
  p2.finish.wait
end

And the output is

try
inside
try
inside
outside
outside

So the mutex has been violated. I've also checked that the class attribute is shared (the memory address of the object is the same)

Any advice? Thanks

remen commented 11 years ago

Hi!

Without investigating it further, I think the issue is that fork_break uses subprocesses instead of threads. Therefore, the two subprocesses don't see each other mutex at all!

Mutexes are typically used to synchronize shared memory, whereas fork_break is built around the use case where you have several rails processes synchronizing against some shared external resource (such as a database). In those cases you need some sort of "external synchronization" such as database locks.

It might be interesting to modify or extend the library to support threads as well but it might be a bit of work! If you want to give it a shot, go right ahead!

remen commented 11 years ago

Closing.