Merge pull request #10891 from chrisroberts/f-trigger-multithread

Update trigger abort behavior when running parallel actions
This commit is contained in:
Chris Roberts 2019-06-05 13:58:44 -07:00 committed by GitHub
commit 2507b68045
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 2 deletions

View File

@ -71,6 +71,10 @@ module Vagrant
thread = Thread.new do
Thread.current[:error] = nil
# Note that this thread is being used for running
# a batch action
Thread.current[:batch_parallel_action] = par
# Record our pid when we started in order to figure out if
# we've forked...
start_pid = Process.pid
@ -160,6 +164,16 @@ module Vagrant
if !errors.empty?
raise Errors::BatchMultiError, message: errors.join("\n\n")
end
# Check if any threads set an exit code and exit if found. If
# multiple threads have exit code values set, the first encountered
# will be the value used.
threads.each do |thread|
if thread[:exit_code]
@logger.debug("Found exit code set within batch action thread. Exiting")
Process.exit!(thread[:exit_code])
end
end
end
end
end

View File

@ -300,8 +300,17 @@ module Vagrant
#
# @param [Integer] code Code to exit Vagrant on
def trigger_abort(exit_code)
@ui.warn(I18n.t("vagrant.trigger.abort"))
Process.exit!(exit_code)
if Thread.current[:batch_parallel_action]
@ui.warn(I18n.t("vagrant.trigger.abort_threaded"))
@logger.debug("Trigger abort within parallel batch action. " \
"Setting exit code and terminating.")
Thread.current[:exit_code] = exit_code
Thread.current.terminate
else
@ui.warn(I18n.t("vagrant.trigger.abort"))
@logger.debug("Trigger abort within non-parallel action, exiting directly")
Process.exit!(exit_code)
end
end
# Calls the given ruby block for execution

View File

@ -297,6 +297,9 @@ en:
Trigger configured to continue on error...
abort: |-
Vagrant has been configured to abort. Terminating now...
abort_threaded: |-
Vagrant has been configured to abort. Vagrant will terminate
after remaining running actions have completed...
start: |-
Running %{type} triggers %{stage} %{action} ...
fire_with_name: |-

View File

@ -63,5 +63,24 @@ describe Vagrant::BatchAction do
subject.action(machine, "up")
subject.run
end
context "with provider supporting parallel actions" do
let(:provider_options) { {parallel: true} }
it "should flag threads as being parallel actions" do
parallel = nil
subject.custom(machine) { |m| parallel = Thread.current[:batch_parallel_action] }
subject.custom(machine) { |*_| }
subject.run
expect(parallel).to eq(true)
end
it "should exit the process if exit_code has been set" do
subject.custom(machine) { |m| Thread.current[:exit_code] = 1}
subject.custom(machine) { |*_| }
expect(Process).to receive(:exit!).with(1)
subject.run
end
end
end
end

View File

@ -423,6 +423,37 @@ describe Vagrant::Plugin::V2::Trigger do
expect(Process).to receive(:exit!).with(3)
subject.send(:trigger_abort, 3)
end
context "when running in parallel" do
let(:thread) {
@t ||= Thread.new do
Thread.current[:batch_parallel_action] = true
Thread.stop
subject.send(:trigger_abort, exit_code)
end
}
let(:exit_code) { 22 }
before do
expect(Process).not_to receive(:exit!)
sleep(0.1) until thread.stop?
end
after { @t = nil }
it "should terminate the thread" do
expect(thread).to receive(:terminate).and_call_original
thread.wakeup
thread.join(1) while thread.alive?
end
it "should set the exit code into the thread data" do
expect(thread).to receive(:terminate).and_call_original
thread.wakeup
thread.join(1) while thread.alive?
expect(thread[:exit_code]).to eq(exit_code)
end
end
end
context "#ruby" do