在MRI Ruby中,我可以这样做:
def transfer
internal_server = self.init_server
pid = fork do
internal_server.run
end
# Make the server process run independently.
Process.detach(pid)
internal_client = self.init_client
# Do other stuff with connecting to internal_server...
internal_client.post('some data')
ensure
# Kill server
Process.kill('KILL', pid) if pid
end
但是上面的代码不会在jRuby中运行,因为它不支持'fork'方法:
NotImplementedError: fork is not available on this platform
在jRuby中有没有替代解决方案?
感谢。
答案 0 :(得分:7)
这是一个很好的问题,但遗憾的是我不相信JVM可以安全地提供您想要的内容,如果您想要的是启动与父进程共享状态的新进程。那是因为forking只复制当前运行的线程。例如,GC线程不会被复制。您不希望在没有GC的情况下运行JVM。
使用fork的唯一半安全方法是立即执行。
查尔斯·纳特(Charles Nutter)在他的blog上首先说你可以使用FFI来分叉和执行,但随后提出了一个警告:以这种方式使用fork + exec的最大问题是你不能 保证*在fork调用和exec调用之间没有任何*。 例如,如果JVM决定使用GC或移动内存,则可以 在JVM进程级别发生致命崩溃。因此,我没有 建议在JRuby中通过FFI使用fork + exec,尽管它很漂亮 凉爽。
我倾向于相信他的建议。
因此,fork和exec会带来一些风险,但保持分叉的JVM会遇到麻烦。
你应该认真考虑塞尔吉奥评论中提出的替代方案。
答案 1 :(得分:1)
我找到了解决方法。我们可以使用JRuby中的内置库FFI来“模拟”MRI中的Process.fork。
# To mimic the Process.fork in MRI Ruby
module JRubyProcess
require 'ffi'
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :fork, [], :int
end
pid = JRubyProcess.fork do
#internal_server.run
end
更多详情:
http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html