diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index 3ee4b3308..2f461f958 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -48,7 +48,13 @@ module Vagrant action_environment = Action::Environment.new(env) action_environment.merge!(options || {}) - callable.call(action_environment) + + # Run the action chain in a busy block, marking the environment as + # interrupted if a SIGINT occurs, and exiting cleanly once the + # chain has been run. + int_callback = lambda { action_environment.error!(:interrupt) } + Busy.busy(int_callback) { callable.call(action_environment) } + exit if action_environment.interrupted? if action_environment.error? # Erroneous environment resulted. Properly display error diff --git a/lib/vagrant/action/environment.rb b/lib/vagrant/action/environment.rb index 02e5698b0..aee42adb8 100644 --- a/lib/vagrant/action/environment.rb +++ b/lib/vagrant/action/environment.rb @@ -50,6 +50,12 @@ module Vagrant !error.nil? end + # Returns a boolean denoting if environment has been interrupted + # with a SIGINT. + def interrupted? + error? && error.first == :interrupt + end + #----------------------------------------------------------------- # Hash with indifferent access #----------------------------------------------------------------- diff --git a/test/vagrant/action/environment_test.rb b/test/vagrant/action/environment_test.rb index d512140f8..17ecae6bd 100644 --- a/test/vagrant/action/environment_test.rb +++ b/test/vagrant/action/environment_test.rb @@ -29,6 +29,12 @@ class ActionEnvironmentTest < Test::Unit::TestCase assert @instance.error? end + should "report interrupted if interrupt error" do + assert !@instance.interrupted? + @instance.error!(:interrupt) + assert @instance.interrupted? + end + should "have indifferent access" do @instance[:foo] = :bar @instance["bar"] = :baz diff --git a/test/vagrant/action_test.rb b/test/vagrant/action_test.rb index ad0efe371..509dfa904 100644 --- a/test/vagrant/action_test.rb +++ b/test/vagrant/action_test.rb @@ -84,6 +84,16 @@ class ActionTest < Test::Unit::TestCase @instance.run(callable, :bar => :foo) end + should "exit if environment was marked as interrupted" do + callable = lambda do |env| + env.error!(:interrupt) + end + + @instance.stubs(:error_and_exit) + @instance.expects(:exit).once + @instance.run(callable) + end + should "error and exit if erroneous environment results" do callable = lambda do |env| env.error!(:key, :foo => :bar)