Skip to content

Commit

Permalink
safe_puts to avoid EPIPE [hashicorpGH-819]
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Mar 18, 2012
1 parent a8ca035 commit 641a8da
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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)

Expand Down
6 changes: 5 additions & 1 deletion lib/vagrant/command/base.rb
@@ -1,12 +1,16 @@
require 'log4r'

require "vagrant/util/safe_puts"

module Vagrant
module Command
# Base class for any CLI commands.
#
# 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
Expand Down Expand Up @@ -41,7 +45,7 @@ def parse_options(opts=nil)

# 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

Expand Down
6 changes: 5 additions & 1 deletion lib/vagrant/command/gem.rb
@@ -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
Expand All @@ -20,7 +24,7 @@ def execute
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
Expand Down
6 changes: 5 additions & 1 deletion lib/vagrant/command/ssh_config.rb
@@ -1,8 +1,12 @@
require 'optparse'

require "vagrant/util/safe_puts"

module Vagrant
module Command
class SSHConfig < Base
include Util::SafePuts

def execute
options = {}

Expand Down Expand Up @@ -36,7 +40,7 @@ def execute

# 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
Expand Down
7 changes: 6 additions & 1 deletion lib/vagrant/ui.rb
@@ -1,5 +1,7 @@
require "log4r"

require "vagrant/util/safe_puts"

module Vagrant
module UI
# Vagrant UIs handle communication with the outside world (typically
Expand Down Expand Up @@ -43,6 +45,8 @@ def ask(*args)
# 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`.
Expand Down Expand Up @@ -112,7 +116,8 @@ def say(type, message, opts=nil)
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.
Expand Down
31 changes: 31 additions & 0 deletions lib/vagrant/util/safe_puts.rb
@@ -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

0 comments on commit 641a8da

Please sign in to comment.