Always provide timeout on thread join to prevent deadlock errors

This commit is contained in:
Chris Roberts 2017-03-27 12:55:15 -07:00
parent 1e6e6a0bf0
commit bfc2af4cf9
4 changed files with 14 additions and 6 deletions

View File

@ -123,7 +123,9 @@ module Vagrant
# Set some attributes on the thread for later # Set some attributes on the thread for later
thread[:machine] = machine thread[:machine] = machine
thread.join if !par if !par
thread.join(THREAD_MAX_JOIN_TIMEOUT) while thread.alive?
end
threads << thread threads << thread
end end
@ -131,7 +133,7 @@ module Vagrant
threads.each do |thread| threads.each do |thread|
# Wait for the thread to complete # Wait for the thread to complete
thread.join thread.join(THREAD_MAX_JOIN_TIMEOUT) while thread.alive?
# If the thread had an error, then store the error to show later # If the thread had an error, then store the error to show later
if thread[:error] if thread[:error]

View File

@ -295,7 +295,7 @@ module Vagrant
# #
# @return [Hash] # @return [Hash]
def checkpoint def checkpoint
@checkpoint_thr.join @checkpoint_thr.join(THREAD_MAX_JOIN_TIMEOUT)
return @checkpoint_thr[:result] return @checkpoint_thr[:result]
end end

View File

@ -12,6 +12,12 @@ module Vagrant
# @return [String] # @return [String]
DEFAULT_SERVER_URL = "https://atlas.hashicorp.com" DEFAULT_SERVER_URL = "https://atlas.hashicorp.com"
# Max number of seconds to wait for joining an active thread.
#
# @return [Integer]
# @note This is not the maxium time for a thread to complete.
THREAD_MAX_JOIN_TIMEOUT = 60
# This holds a global lock for the duration of the block. This should # This holds a global lock for the duration of the block. This should
# be invoked around anything that is modifying process state (such as # be invoked around anything that is modifying process state (such as
# environmental variables). # environmental variables).

View File

@ -53,7 +53,7 @@ module Vagrant
# We're being called in a trap-context. Wrap in a thread. # We're being called in a trap-context. Wrap in a thread.
Thread.new do Thread.new do
@logger.info { "#{method}: #{message}" } @logger.info { "#{method}: #{message}" }
end.join end.join(THREAD_MAX_JOIN_TIMEOUT)
end end
end end
end end
@ -128,7 +128,7 @@ module Vagrant
@lock.synchronize do @lock.synchronize do
safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}") safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
end end
end.join end.join(THREAD_MAX_JOIN_TIMEOUT)
end end
end end
@ -244,7 +244,7 @@ module Vagrant
safe_puts(format_message(type, message, **opts), safe_puts(format_message(type, message, **opts),
io: channel, printer: printer) io: channel, printer: printer)
end end
end.join end.join(THREAD_MAX_JOIN_TIMEOUT)
end end
def format_message(type, message, **opts) def format_message(type, message, **opts)