2012-08-05 16 views
5

In MRI Rubino posso fare questo:Alternativa per spawnare un processo con 'fork' in 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 

Tuttavia il codice di cui sopra non verrà eseguito in JRuby, perché non supporta il metodo 'forchetta':

NotImplementedError: fork is not available on this platform 

Esiste una soluzione alternativa per questo in jRuby?

Grazie.

+1

Le risposte a [questa domanda] (http://stackoverflow.com/questions/5349629/ruby-daemons-and-jruby-alternative-options) potrebbero esserti utili. –

+0

Grazie, [Spoon] (https://github.com/headius/spoon) sembra interessante, ma non risolve il mio problema, perché genera semplicemente un processo esterno senza condividere lo stato del thread corrente. In realtà, ho bisogno di "processo figlio" è un altro interprete Ruby e il processo figlio condividerà lo stato del thread corrente. –

+0

@ La risposta di Kelvin è davvero buona. Penso che valga la pena chiedere perché vuoi fork(). Fork() è una chiamata di sistema che è incorporata nei sistemi basati su unix. D'altra parte, Java è progettato per essere eseguito ovunque. Se hai bisogno di fork, suggerirei che JRuby è l'implementazione ruby ​​sbagliata per te. – Stewart

risposta

1

Ho trovato la soluzione per questo. Possiamo usare la libreria FFI incorporata in JRuby per 'simulare' il 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 

Maggiori dettagli:

https://github.com/ffi/ffi

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

+1

Charles Nutter suggerisce che è [pericoloso lanciare usando jruby] (https://github.com/jruby/jruby/issues/246) a meno che non abbia intenzione di eseguire immediatamente.L'esecuzione di exec causerà l'uscita della JVM biforcuta, motivo per cui è sicura. – Kelvin

7

Questa è una buona domanda, ma purtroppo non credo che la JVM può tranquillamente darti quello che vuoi, se quello che voglio è iniziare un nuovo processo che condivide lo stato con il processo genitore. Questo perché la biforcazione copia solo il thread attualmente in esecuzione. I thread GC, ad esempio, non vengono copiati. Non vuoi eseguire una JVM senza GC.

L'unico modo semi-sicuro di utilizzare la forcella è eseguire immediatamente dopo.

Charles Nutter, sul suo blog, prima dice che si può utilizzare FFI alla forcella e exec, ma fornisce quindi un avvertimento:

Il problema più grande con l'utilizzo di fork + exec in questo modo è che si può' t Garanzia * * * * non avviene tra la chiamata a forcella e la chiamata exec. Se, ad esempio, la JVM decide di utilizzare GC o di spostare la memoria, è possibile che abbia un arresto anomalo a livello del processo JVM. Per questo motivo, non mi raccomando di usare fork + exec via FFI in JRuby, anche se è abbastanza bello da .

Mi piacerebbe fidarmi del suo consiglio qui.

Quindi, un fork e un exec corrono dei rischi, ma mantenere la JVM biforcuta in giro è un problema.

Si dovrebbe prendere seriamente in considerazione le alternative suggerite dal commento di Sergio.