Run only a single trap thread at any given time. Ensure that trap threads are joined after a busy block ends.

This commit is contained in:
Mitchell Hashimoto 2010-02-15 18:37:20 -08:00
parent 874eb70911
commit 97f9d4c5ef
2 changed files with 41 additions and 2 deletions

View File

@ -12,6 +12,7 @@ module Vagrant
@@busy = false @@busy = false
@@mutex = Mutex.new @@mutex = Mutex.new
@@trap_thread = nil
class << self class << self
def busy? def busy?
@ -34,6 +35,9 @@ module Vagrant
# busy back to some sane state. # busy back to some sane state.
Busy.busy = false Busy.busy = false
# Make sure that the trap thread completes, if it is running
trap_thread.join if trap_thread
# And restore the INT trap to the default # And restore the INT trap to the default
Signal.trap("INT", "DEFAULT") Signal.trap("INT", "DEFAULT")
end end
@ -41,7 +45,7 @@ module Vagrant
end end
def wait_for_not_busy(sleeptime=5) def wait_for_not_busy(sleeptime=5)
Thread.new do @@trap_thread ||= Thread.new do
# Wait while the app is busy # Wait while the app is busy
loop do loop do
break unless busy? break unless busy?
@ -50,9 +54,20 @@ module Vagrant
end end
# Exit out of the entire script # Exit out of the entire script
logger.info "Exiting vagrant..."
exit exit
end end
end end
# Used for testing
def reset_trap_thread!
@@trap_thread = nil
end
# Returns the trap thread
def trap_thread
@@trap_thread
end
end end
end end
end end

View File

@ -2,7 +2,19 @@ require File.join(File.dirname(__FILE__), '..', 'test_helper')
class BusyTest < Test::Unit::TestCase class BusyTest < Test::Unit::TestCase
context "waiting for not busy" do context "waiting for not busy" do
# TODO: Need to test this method setup do
Vagrant::Busy.reset_trap_thread!
end
should "run in a thread" do
Thread.expects(:new).once.returns(nil)
Vagrant::Busy.wait_for_not_busy
end
should "not start a thread multiple times" do
Thread.expects(:new).once.returns("foo")
Vagrant::Busy.wait_for_not_busy
end
end end
context "during an action in a busy block" do context "during an action in a busy block" do
@ -27,6 +39,18 @@ class BusyTest < Test::Unit::TestCase
assert !Vagrant.busy? assert !Vagrant.busy?
end end
should "complete the trap thread even if an exception occurs" do
trap_thread = mock("trap_thread")
trap_thread.expects(:join).once
Vagrant::Busy.stubs(:trap_thread).returns(trap_thread)
assert_raise Exception do
Vagrant.busy do
raise Exception
end
end
end
should "report busy to the outside world regardless of thread" do should "report busy to the outside world regardless of thread" do
Thread.new do Thread.new do
Vagrant.busy do Vagrant.busy do