vaguerent/lib/vagrant/util/safe_exec.rb
Josh Soref 1a5ddea9f4 Spelling fixes
* account
* addresses
* administrator
* afterwards
* because
* bridgeable
* capabilities
* capability
* checksum
* configuration
* configuration for
* configure
* criteria
* delimited
* delivered
* derivatives
* description
* detect
* directory
* display
* downloading
* during
* electric
* enabling
* encountered
* equivalent
* executable
* executed
* hashicorp
* hypervisor
* hyphens
* implementation
* incorporate
* inheritance
* initialize
* instance
* instead
* interactions
* invocable
* machine
* maximum
* message
* mounting
* overridden
* overwrite
* paramiko
* preparing
* provides
* provisioning
* recursively
* requested
* resetting
* retryable
* running
* satisfied
* searching
* sometimes
* specified
* successfully
* synced folders
* unauthorized
* underlying
* userprofile
* vagrant
* vagrantfile
* variable
* various
* version
* virtual
* windows
2018-03-14 14:41:04 +00:00

76 lines
2.9 KiB
Ruby

module Vagrant
module Util
# This module provides a `safe_exec` method which is a drop-in
# replacement for `Kernel.exec` which addresses a specific issue
# which manifests on OS X 10.5 (GH-51) and perhaps other operating systems.
# This issue causes `exec` to fail if there is more than one system
# thread. In that case, `safe_exec` automatically falls back to
# forking.
class SafeExec
@@logger = Log4r::Logger.new("vagrant::util::safe_exec")
def self.exec(command, *args)
# Create a list of things to rescue from. Since this is OS
# specific, we need to do some defined? checks here to make
# sure they exist.
rescue_from = []
rescue_from << Errno::EOPNOTSUPP if defined?(Errno::EOPNOTSUPP)
rescue_from << Errno::E045 if defined?(Errno::E045)
rescue_from << SystemCallError
fork_instead = false
begin
if fork_instead
if Vagrant::Util::Platform.windows?
@@logger.debug("Using subprocess because windows platform")
args = args.dup << {notify: [:stdout, :stderr]}
result = Vagrant::Util::Subprocess.execute(command, *args) do |type, data|
case type
when :stdout
@@logger.info(data, new_line: false)
when :stderr
@@logger.info(data, new_line: false)
end
end
Kernel.exit(result.exit_code)
else
pid = fork
Kernel.exec(command, *args)
Process.wait(pid)
end
else
if Vagrant::Util::Platform.windows?
# Re-generate strings to ensure common encoding
@@logger.debug("Converting command and arguments to common UTF-8 encoding for exec.")
@@logger.debug("Command: `#{command.inspect}` Args: `#{args.inspect}`")
begin
command = "#{command}".encode("UTF-8")
rescue Encoding::UndefinedConversionError => e
@@logger.warn("Failed to convert command - #{e.class}: #{e} (`#{command}`)")
end
args = args.map do |arg|
begin
"#{arg}".encode("UTF-8")
rescue Encoding::UndefinedConversionError => e
@@logger.warn("Failed to convert command argument - #{e.class}: #{e} (`#{arg}`)")
arg
end
end
@@logger.debug("Converted - Command: `#{command.inspect}` Args: `#{args.inspect}`")
end
Kernel.exec(command, *args)
end
rescue *rescue_from
# We retried already, raise the issue and be done
raise if fork_instead
# The error manifested itself, retry with a fork.
fork_instead = true
retry
end
end
end
end
end