safe_puts to avoid EPIPE [GH-819]

This commit is contained in:
Mitchell Hashimoto 2012-03-18 17:41:26 -06:00
parent a8ca0353e9
commit 641a8daac8
6 changed files with 53 additions and 4 deletions

View File

@ -8,6 +8,7 @@
setting. [GH-808]
- `vagrant ssh` now works on Solaris, where `IdentitiesOnly` was not
an available option. [GH-820]
- Output works properly in the face of broken pipes. [GH-819]
## 1.0.1 (March 11, 2012)

View File

@ -1,5 +1,7 @@
require 'log4r'
require "vagrant/util/safe_puts"
module Vagrant
module Command
# Base class for any CLI commands.
@ -7,6 +9,8 @@ module Vagrant
# This class provides documentation on the interface as well as helper
# functions that a command has.
class Base
include Util::SafePuts
def initialize(argv, env)
@argv = argv
@env = env
@ -41,7 +45,7 @@ module Vagrant
# Add the help option, which must be on every command.
opts.on_tail("-h", "--help", "Print this help") do
puts opts.help
safe_puts(opts.help)
return nil
end

View File

@ -1,9 +1,13 @@
require "rubygems"
require "rubygems/gem_runner"
require "vagrant/util/safe_puts"
module Vagrant
module Command
class Gem < Base
include Util::SafePuts
def execute
# Bundler sets up its own custom gem load paths such that our
# own gems are never loaded. Therefore, give an error if a user
@ -20,7 +24,7 @@ module Vagrant
if @argv.empty? || @argv.include?("-h") || @argv.include?("--help")
@env.ui.info(I18n.t("vagrant.commands.gem.help_preamble"),
:prefix => false)
puts
safe_puts
end
# We just proxy the arguments onto a real RubyGems command

View File

@ -1,8 +1,12 @@
require 'optparse'
require "vagrant/util/safe_puts"
module Vagrant
module Command
class SSHConfig < Base
include Util::SafePuts
def execute
options = {}
@ -36,7 +40,7 @@ module Vagrant
# Render the template and output directly to STDOUT
template = "commands/ssh_config/config"
$stdout.puts(Util::TemplateRenderer.render(template, variables))
safe_puts(Util::TemplateRenderer.render(template, variables))
end
end
end

View File

@ -1,5 +1,7 @@
require "log4r"
require "vagrant/util/safe_puts"
module Vagrant
module UI
# Vagrant UIs handle communication with the outside world (typically
@ -43,6 +45,8 @@ module Vagrant
# This is a UI implementation that outputs the text as is. It
# doesn't add any color.
class Basic < Interface
include Util::SafePuts
# Use some light meta-programming to create the various methods to
# output text to the UI. These all delegate the real functionality
# to `say`.
@ -112,7 +116,8 @@ module Vagrant
channel = type == :error || opts[:channel] == :error ? $stderr : $stdout
# Output!
channel.send(printer, format_message(type, message, opts))
safe_puts(format_message(type, message, opts),
:io => channel, :printer => printer)
end
# This is called by `say` to format the message for output.

View File

@ -0,0 +1,31 @@
module Vagrant
module Util
# This module provides a `safe_puts` method which outputs to
# the given IO object, and rescues any broken pipe errors and
# ignores them. This is useful in cases where you're outputting
# to stdout, for example, and the stdout is closed, but you want to
# keep running.
module SafePuts
# Uses `puts` on the given IO object and safely ignores any
# Errno::EPIPE.
#
# @param [String] message Message to output.
# @param [Hash] opts Options hash.
def safe_puts(message=nil, opts=nil)
message ||= ""
opts = {
:io => $stdout,
:printer => :puts
}.merge(opts || {})
begin
opts[:io].send(opts[:printer], message)
rescue Errno::EPIPE
# This is what makes this a `safe` puts.
return
end
end
end
end
end