Allow closing a Vagrant::Util::Subprocess's STDIN
Previously, there was no way to close the STDIN stream of a subprocess,
so commands that read from stdin in a subprocess would hang forever,
such as `/bin/sh -s`. If one tried to close the stdin, the
IO.select() call in Subprocess#execute would raise an error for calling
select() on a closed IO.
Here's a concrete example of a command that needs to close STDIN to work
properly:
```ruby
script = SOME_VERY_LONG_STRING
command = %w(ssh foo.example.com /bin/sh -s foo bar)
result = ::Vagrant::Util::Subprocess.execute(*command) do |type, data_or_io|
if type == :stdin
data_or_io.write(script)
data_or_io.write("\n")
data_or_io.close
next
end
puts "Remote: #{data_or_io}"
end
```
This commit is contained in:
parent
9c299a2a35
commit
ceb69e6266
@ -144,10 +144,11 @@ module Vagrant
|
||||
# Record the start time for timeout purposes
|
||||
start_time = Time.now.to_i
|
||||
|
||||
open_readers = [stdout, stderr]
|
||||
open_writers = notify_stdin ? [process.io.stdin] : []
|
||||
@logger.debug("Selecting on IO")
|
||||
while true
|
||||
writers = notify_stdin ? [process.io.stdin] : []
|
||||
results = ::IO.select([stdout, stderr], writers, nil, 0.1)
|
||||
results = ::IO.select(open_readers, open_writers, nil, 0.1)
|
||||
results ||= []
|
||||
readers = results[0]
|
||||
writers = results[1]
|
||||
@ -178,8 +179,14 @@ module Vagrant
|
||||
break if process.exited?
|
||||
|
||||
# Check the writers to see if they're ready, and notify any listeners
|
||||
if writers && !writers.empty?
|
||||
yield :stdin, process.io.stdin if block_given?
|
||||
if writers && !writers.empty? && block_given?
|
||||
yield :stdin, process.io.stdin
|
||||
|
||||
# if the callback closed stdin, we should remove it, because
|
||||
# IO.select() will throw if called with a closed io.
|
||||
if process.io.stdin.closed?
|
||||
open_writers = []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user