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.
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.
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