在jRuby中使用'fork'生成进程的替代方法?

Blu*_*ith 5 ruby jruby

在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
Run Code Online (Sandbox Code Playgroud)

但是上面的代码不会在jRuby中运行,因为它不支持'fork'方法:

NotImplementedError: fork is not available on this platform
Run Code Online (Sandbox Code Playgroud)

在jRuby中有没有替代解决方案?

谢谢.

Kel*_*vin 7

这是一个很好的问题,但遗憾的是我不相信JVM可以安全地为您提供您想要的内容,如果您想要的是启动一个与父进程共享状态的新进程.那是因为forking只复制当前运行的线程.例如,GC线程不会被复制.您不希望在没有GC的情况下运行JVM.

使用fork的唯一半安全方法是在之后立即执行.

Charles Nutter在他的博客上首先说你可以使用FFI来分叉和执行,但随后提供了一个警告:

以这种方式使用fork + exec的最大问题是你不能保证在fork调用和exec调用之间没有*.例如,如果JVM决定使用GC或移动内存,则可能会在JVM进程级别发生致命崩溃.因此,我建议不要在JRuby中通过FFI使用fork + exec,尽管它非常酷.

我倾向于相信他的建议.

因此,fork和exec会带来一些风险,但保持分叉的JVM会遇到麻烦.

你应该认真考虑塞尔吉奥评论中提出的替代方案.


Blu*_*ith 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
Run Code Online (Sandbox Code Playgroud)

更多细节:

https://github.com/ffi/ffi

http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html