2012-08-05 31 views
5

在MRI紅寶石我可以這樣做:在jRuby中用'fork'產生一個進程的替代方案?

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 

但是上面的代碼將無法在JRuby中運行,因爲它不支持「叉」方法:

NotImplementedError: fork is not available on this platform 

是否有任何替代解決方案這在jRuby?

謝謝。

+1

對[此問題](http://stackoverflow.com/questions/5349629/ruby-daemons-and-jruby-alternative-options)的答案可能對您有用。 – 2012-08-05 17:21:35

+0

謝謝[Spoon](https://github.com/headius/spoon)似​​乎很有趣,但它不能解決我的問題,因爲它只是產生一個外部進程而不共享當前線程的狀態。實際上,我需要'子進程'是另一個Ruby解釋器,子進程將共享當前線程的狀態。 – 2012-08-05 18:03:14

+0

@ Kelvin的回答非常好。我認爲可能值得問一下爲什麼要fork()。 Fork()是一個內置於基於unix的系統的系統調用。另一方面,Java旨在在任何地方運行。如果你需要fork,那麼我會建議JRuby是你錯誤的ruby實現。 – Stewart 2015-04-22 04:45:08

回答

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 

更多細節:

https://github.com/ffi/ffi

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

+1

Charles Nutter建議,除非你立即執行,否則它[使用jruby fork(危險)](https://github.com/jruby/jruby/issues/246)。執行exec會導致分叉的JVM退出,這就是爲什麼它是安全的。 – Kelvin 2012-11-09 23:21:33

7

這是一個很好的問題,但不幸的是我不相信JVM可以安全地給你你想要什麼,如果你想要啓動一個與父進程共享狀態的新進程。這是因爲分叉只複製當前正在運行的線程。 GC線程(例如)不會被複制。您不想在沒有GC的情況下運行JVM。

使用fork的唯一半安全方式是在執行後立即執行。

查爾斯·納特,他blog,第一說,你可以使用FFI叉和exec,但隨後提供了一個警告:

以這種方式使用叉子+ Exec中的最大的問題是,你可以」 t 保證*在fork調用和exec調用之間無*發生。 例如,如果JVM決定GC或移動內存,那麼在JVM進程級別,您可能會發生致命的崩潰 。因此,我並不推薦在JRuby中通過FFI使用fork + exec來實現 ,儘管它很酷。

我會傾向於相信他的建議。因此,一個fork和exec會帶來一些風險,但是保持分叉的JVM在尋求麻煩。

您應該認真考慮Sergio的評論提出的替代方案。