Christian Johansen
Christian Johansen

Reputation: 2031

EventMachine DeferrableChildProcess error handling

I'm having problems making EventMachine::DeferrableChildProcess.open actually do any sort of error handling. Hopefully I'm doing it wrong. Here's an example:

require "eventmachine"
EM.run do
  cp = EM::DeferrableChildProcess.open("ls /trololo")
  cp.callback { |data| puts "Received some data: '#{data}'" }
  cp.errback { |err| puts "Failed: #{err.inspect}" }
end

I would expect the outcome of this piece of code (assuming you don't actually have a /trolol directory on your system) to be: "Failed: <SomeErrorObject>". Instead, I get "Received some data: ''". Adding insult to injury, the error message caused by ls ("ls: cannot access /trololo: No such file or directory") is somehow printed to stderr.

Am I doing something wrong, or is there basically no error handling in EM::DeferrableChildProcess.open? I got similar results with EM.popen.

Upvotes: 3

Views: 362

Answers (1)

Christian Johansen
Christian Johansen

Reputation: 2031

Ok, looking at EventMachine's implementation, I can clearly see that DeferrableChildProcess simply assumes success - the errback will never be called. I guess the intention is that you in your own callback have to do get_status to figure out what's going on. I didn't care for that API, so I wrote an error-handling DeferrableChildProcess:

class DeferrableChildProcess < EventMachine::Connection
  include EventMachine::Deferrable

  def initialize
    super
    @data = []
  end

  def self.open cmd
    EventMachine.popen(cmd, DeferrableChildProcess)
  end

  def receive_data data
    @data << data
  end

  def unbind
    status = get_status
    if status.exitstatus != 0
      fail(status)
    else
      succeed(@data.join, status)
    end
  end
end

Upvotes: 3

Related Questions