ruby picture

RCR 206: Make popen3 raise an exception on failure

Submitted by Paul Brannan (Wed Feb 04 15:02:53 UTC 2004)

Abstract

Open3.popen3 should raise an exception if the exec call fails.

Problem

If I write code like this:

  require 'open3'
  Open3.popen3('sldkfjsldf')</pre>

then (assuming there is no binary called "sldkfjsldf" in the path) this will silently fail. This is because popen3 uses a "double fork" to detach the child process from the parent.

Proposal

Open3.popen3 should be changed to catch the exception from exec() and marshal it to the parent process.

Analysis

This solution retains the "double fork" but will marshal any exceptions to the parent process and re-raise them there.

Implementation

A sample implementation can be found at:
  http://www.rubystuff.org/treasures/RubyTreasures-0.5/lib/open3y.rb.html
ruby picture
Comments Current voting

I respectfully disagree. My opinion is that it's your job to check the error filehandle, not Ruby's job to raise an exception. If you're not checking the error filehandle, you're not using the module the way it was meant to be used.

For your example it should be:

fin, fout, ferr = Open3.popen3('sldkfjsldf')
x = ferr.gets
if x
   raise SomeError, "Something wrong here: #{x}"
end
Besides, there are times that I want to grab the error, but not raise an exception. In most cases, the "error" may simply be that the command returned data to the error handle, but did not fail per se. - Daniel Berger


Actually, I'm for this one. Here's my reasoning: if a call to exec fails, it throws an exception. From a consistency perspective, I would expect popen3 to do the same, since conceptually it is just another way to do an exec. To qualify my stance, I only think popen3 should throw an exception when exec would--if the invoked command simply "fails" by writing to stderr and/or returning non-zero, then no exception should be raised.

-- Jamis Buck


Checking for the presence of data on the err handle isn't sufficient to determine if exec failed. If the child process writes to stderr, it will show up when I read from ferr.

-- Paul Brannan


I just got burnt by this one today. Open3 is actually pretty useless, because there's no way to tell whether or not the command you're trying to run even exists. On Windows, at least, stderr is empty for a non-existant command--it just fails silently.


I think the critical issue here is how do you distinguish between the following cases...

  • The executable doesn't exist.
  • The executable exists, but is corrupt so dies on loading.
  • The executable exists, is good, but exits immediately with non-zero return code.
  • The executable is perfectly OK, but exits immediately with zero return code for some Good reason.
  • The executable was good, printed out one byte on {STDOUT or STDERR}, exited with (non-)?zero return code.

If someone can display some good clean platform neutral ruby code that prints out a simple message as to which of each of these cases occurred, I will be convinced that there is no issue here.


Strongly opposed 0
Opposed 1
Neutral 0
In favor 6
Strongly advocate 1
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .