Skip to content

Instantly share code, notes, and snippets.

@gruis
Forked from tokland/external-command.rb
Created November 2, 2011 11:32
Show Gist options
  • Save gruis/1333428 to your computer and use it in GitHub Desktop.
Save gruis/1333428 to your computer and use it in GitHub Desktop.
Capture stderr data on EventMachine.popen
#!/usr/bin/env ruby -wW1
require 'eventmachine'
module EventMachine
# @see http://eventmachine.rubyforge.org/EventMachine.html#M000491
def self.popen3(cmd, handler=nil, *args)
klass = klass_from_handler(Connection, handler, *args)
w = Shellwords::shellwords(cmd)
w.unshift(w.first) if w.first
new_stderr = $stderr.dup
rd, wr = IO::pipe
$stderr.reopen wr
s = invoke_popen(w)
$stderr.reopen new_stderr
klass.new(s, *args).tap do |c|
EM.attach(rd, Popen3StderrHandler, c)
@conns[s] = c
yield(c) if block_given?
end
end
class Popen3StderrHandler < EventMachine::Connection
def initialize(connection)
@connection = connection
end
def receive_data(data)
@connection.receive_stderr(data)
end
end # class::Popen3StderrHandler
end # module::EventMachine
class CountRecvr < EventMachine::Connection
include EventMachine::Deferrable
class << self
def start(cmd, *args)
EM.popen3(cmd, self, *args).tap { |o| yield(o) if block_given? }
end
end # << self
def initialize(cnt = 5)
$stderr.puts("#{self.class}.new(#{cnt}) -> #{self}")
@cnt = cnt
@data = ""
end
def post_init
$stderr.puts "post init from parent"
send_data("#{@cnt}\n")
end
def receive_data(d)
puts "receive data from child: #{d.dump}"
@data << d
@data.include?("#{self}") && raise("stderr is shared by parent and child!")
end
alias :receive_stderr :receive_data
def unbind
get_status.exitstatus == 0 ? succeed(@data, self) : fail(@data, self)
end
end # class::CountRecvr < EventMachine::Connection
# @see http://eventmachine.rubyforge.org/EventMachine.html#M000491
# @see https://gist.github.com/535644
EM.run {
CountRecvr.start(%q{ruby -e' gets.to_i.times{ |i| $stderr.puts i+1; sleep 1 }'}, ARGV[0] || 3) do |cntr|
cntr.callback { EM.stop }
cntr.errback { EM.stop }
end
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment