Skip to content

Instantly share code, notes, and snippets.

@tokland
Forked from careo/external-command.rb
Created August 18, 2010 18:01
Show Gist options
  • Save tokland/535644 to your computer and use it in GitHub Desktop.
Save tokland/535644 to your computer and use it in GitHub Desktop.
Capture stderr data on EventMachine.popen
require 'rubygems'
require 'eventmachine'
$stdout.sync = true
$stderr.sync = true
EM.run {
EM.add_periodic_timer(0.1) {
$stdout.write "stdout\n"
}
EM.add_periodic_timer(0.1) {
$stderr.write "stderr\n"
}
EM.add_timer(1) {
$stdout.write "stopping from stdout...\n"
$stderr.write "stopping from stderr...\n"
EM.stop
}
}
require 'rubygems'
require 'eventmachine'
if RUBY_VERSION < "1.8.7"
def __method__
caller = /`(.*)'/
Kernel.caller.first.split(caller).last.to_sym
end
end
def log *message
p [Time.now, *message]
end
module EventMachine
def self.popen3(*args)
new_stderr = $stderr.dup
rd, wr = IO::pipe
$stderr.reopen wr
connection = EM.popen(*args)
$stderr.reopen new_stderr
EM.attach rd, Popen3StderrHandler, connection
connection
end
class Popen3StderrHandler < EventMachine::Connection
def initialize(connection)
@connection = connection
end
def receive_data(data)
@connection.receive_stderr(data)
end
end
end
class MyProcess < EventMachine::Connection
def initialize *args
log __method__, args
end
def receive_data data
log __method__, data
end
def receive_stderr data
log __method__, data
end
def unbind
log __method__
end
end
if __FILE__ == $0
cmd = "ruby #{File.dirname(__FILE__)}/external-command.rb"
EM.run do
EM.next_tick do
$stderr.puts "stderr before"
EM.popen3 cmd, MyProcess
$stderr.puts "stderr after"
end
EM.add_timer(2) do
log :exit
EM.stop
end
end
end
@cjohansen
Copy link

Thanks guys! I took the core idea here, ran with it and published http://rubygems.org/gems/em_pessimistic, which fixes this annoyance with EM.popen, and adds proper error handling to DeferrableChildProcess

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment