2012-08-05 11 views
5

En la RM Ruby I puede hacer esto:Alternativa para engendrar un proceso con 'tenedor' en jRuby?

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 

Sin embargo, el código no se ejecutará en jruby, ya que no es compatible con el método 'tenedor':

NotImplementedError: fork is not available on this platform 

¿Hay alguna solución alternativa esto en jRuby?

Gracias.

+1

Las respuestas a [esta pregunta] (http://stackoverflow.com/questions/5349629/ruby-daemons-and-jruby-alternative-options) pueden serle útiles. –

+0

Gracias, [Spoon] (https://github.com/headius/spoon) parece interesante, pero no resuelve mi problema, ya que genera un proceso externo sin compartir el estado del hilo actual. En realidad, necesito 'proceso hijo' es otro intérprete de Ruby y el proceso secundario compartirá el estado del hilo actual. –

+0

@ La respuesta de Kelvin es realmente buena. Creo que valdría la pena preguntar por qué quieres fork(). Fork() es una llamada al sistema que está integrada en sistemas basados ​​en Unix. Por otro lado, Java está destinado a ejecutarse en cualquier lugar. Si necesita bifurcar, sugeriría que JRuby sea la implementación de ruby ​​equivocada para usted. – Stewart

Respuesta

1

Encontré la solución para esto. Podemos usar la biblioteca incorporada FFI en JRuby para 'simular' Process.fork en 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 

Más detalles:

https://github.com/ffi/ffi

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

+1

Charles Nutter sugiere que es [peligroso tenedor usando jruby] (https://github.com/jruby/jruby/issues/246) a menos que vaya a ejecutar de inmediato.Hacer un exec hará que la JVM ahorquillada salga, por lo que es seguro. – Kelvin

7

Esta es una buena pregunta, pero por desgracia no creo que la JVM se puede dar con seguridad lo que quiere, si lo que querer es comenzar un nuevo proceso que comparte estado con el proceso principal. Esto se debe a que forking solo copia el hilo que se está ejecutando actualmente. Los hilos del GC, por ejemplo, no se copian. No desea ejecutar una JVM sin GC.

La única forma semi segura de usar la horquilla es ejecutarla inmediatamente después.

Charles Nutter, en su blog, dice primero puede utilizar FFI a la mesa y exec, pero luego ofrece una advertencia:

El mayor problema con el uso de tenedor + exec de esta manera es que se puede' t garantía * nada * ocurre entre la llamada de la tenedor y la llamada del ejecutivo. Si, por ejemplo, la JVM decide GC o mueve la memoria, puede tener un bloqueo fatal en el nivel de proceso de JVM. Debido a eso, no recomiendo el uso de fork + exec a través de FFI en JRuby, a pesar de que es bastante genial.

Tendería a confiar en su consejo aquí.

Por lo tanto, un fork y un ejecutivo conllevan cierto riesgo, pero mantener la JVM bifurcada es una tarea problemática.

Debería considerar seriamente las alternativas sugeridas por el comentario de Sergio.