Reputation: 21096
The following code stucks in MRI 1.9.3 but seems to work in 2.0.0 and 2.1.2.
def run_in_isolation
# From http://stackoverflow.com/a/1076445/841064
read, write = IO.pipe
pid = fork do
read.close
result = yield
Marshal.dump(result, write)
exit
end
write.close
result = read.read
Process.wait(pid)
raise 'child failed' if result.empty?
Marshal.load(result)
end
run_in_isolation do
require 'childprocess' # http://rubygems.org/gems/childprocess
process = ChildProcess.build("ruby", "-e", "sleep")
process.start
end
Why? And how can I make it working in 1.9.3?
Upvotes: 0
Views: 82
Reputation: 6058
Your code has two problems:
You're trying to Marshal.load
a ChildProcess process, i.e. the return value from process.start
in the parent where ChildProcess was never loaded. Since the module (ChildProcess
) does not exist in the parent process, this will raise an ArgumentError on any Ruby version.
On 1.9, the write side of the created pipe will be inherited by the sleeping Ruby process started through ChildProcess
. Since the write side isn't closed, the read()
call will hang. In Ruby 2.X, the default behaviour was changed so that non-standard file descriptors are closed on exec
. To solve this (in a cross-platform way) you can call ChildProcess.close_on_exec(write)
just before you yield.
Upvotes: 1