Require what to be notified for with block and Subprocess.execute

There was an issue before where the stdin buffer would always have space
so it would always yield that block and Ruby would spin at 100%. Now we
require all callers to say what they want to listen for. This drops
CPU down to almost nothing.

See GH-832
This commit is contained in:
Mitchell Hashimoto 2012-06-01 17:00:50 +02:00
parent 903fd3acdc
commit 1a6ae81aa9
4 changed files with 28 additions and 4 deletions

View File

@ -314,6 +314,9 @@ module Vagrant
@logger.info("Interrupted.")
end
# Append in the options for subprocess
command << { :notify => [:stdout, :stderr] }
Util::Busy.busy(int_callback) do
Subprocess.execute(@vboxmanage_path, *command, &block)
end

View File

@ -63,7 +63,7 @@ module Vagrant
end
end
Vagrant::Util::Subprocess.execute(command, &block)
Vagrant::Util::Subprocess.execute(command, :notify => [:stdout, :stderr], &block)
end
# Run a shell command within the VM. The command will run within a

View File

@ -29,8 +29,27 @@ module Vagrant
def execute
# Get the timeout, if we have one
timeout = @options[:timeout]
# Get the working directory
workdir = @options[:workdir] || Dir.pwd
# Get what we're interested in being notified about
notify = @options[:notify] || []
notify = [notify] if !notify.is_a?(Array)
if notify.empty? && block_given?
# If a block is given, subscribers must be given, otherwise the
# block is never called. This is usually NOT what you want, so this
# is an error.
message = "A list of notify subscriptions must be given if a block is given"
raise ArgumentError, message
end
# Let's get some more useful booleans that we access a lot so
# we're not constantly calling an `include` check
notify_stderr = notify.include?(:stderr)
notify_stdin = notify.include?(:stdin)
notify_stdout = notify.include?(:stdout)
# Build the ChildProcess
@logger.info("Starting process: #{@command.inspect}")
process = ChildProcess.build(*@command)
@ -80,7 +99,8 @@ module Vagrant
@logger.debug("Selecting on IO")
while true
results = IO.select([stdout, stderr], [process.io.stdin], nil, timeout || 5)
writers = notify_stdin ? [process.io.stdin] : []
results = IO.select([stdout, stderr], writers, nil, timeout || 5)
readers, writers = results
# Check if we have exceeded our timeout

View File

@ -51,7 +51,8 @@ module Acceptance
options = argN.last.is_a?(Hash) ? argN.pop : {}
options = {
:workdir => @workdir,
:env => @env
:env => @env,
:notify => [:stdin, :stderr, :stdout]
}.merge(options)
# Add the options to be passed on
@ -59,7 +60,7 @@ module Acceptance
# Execute, logging out the stdout/stderr as we get it
@logger.info("Executing: #{[command].concat(argN).inspect}")
Vagrant::Util::Subprocess.execute(command, *argN) do |type, data|
Vagrant::Util::Subprocess.execute(command *argN) do |type, data|
@logger.debug("#{type}: #{data}") if type == :stdout || type == :stderr
yield type, data if block_given?
end