Alternative for spawning a process with 'fork&

2019-06-21 13:13发布

In MRI Ruby I can do this:

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

However the above code will not run in jRuby, because it does not support 'fork' method:

NotImplementedError: fork is not available on this platform

Is there any alternative solution for this in jRuby?

Thanks.

标签: ruby jruby
2条回答
祖国的老花朵
2楼-- · 2019-06-21 13:21

This is a good question, but unfortunately I don't believe the JVM can safely give you what you want, if what you want is to start a new process that shares state with the parent process. That's because forking only copies the currently running thread. GC thread(s) for example, aren't copied. You don't want to be running a JVM without GC.

The only semi-safe way of using fork is to exec immediately afterwards.

Charles Nutter, on his blog, first says you can use FFI to fork and exec, but then provides a caveat:

The biggest problem with using fork+exec in this way is that you can't guarantee *nothing* happens between the fork call and the exec call. If, for example, the JVM decides to GC or move memory around, you can have a fatal crash at the JVM process level. Because of that, I don't recommend using fork + exec via FFI in JRuby, even though it's pretty cool.

I would tend to trust his advice here.

So, a fork and exec carries some risk, but keeping the forked JVM around is asking for trouble.

You should seriously consider the alternatives suggested by Sergio's comment.

查看更多
狗以群分
3楼-- · 2019-06-21 13:40

I found out the solution for this. We can use the built-in library FFI in JRuby to 'simulate' the Process.fork in MRI.

# 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

More details:

https://github.com/ffi/ffi

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

查看更多
登录 后发表回答