Альтернатива для создания процесса с «вилкой» в jRuby?

В МРТ Ruby я могу сделать это:

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, потому что он не поддерживает метод 'fork':

NotImplementedError: fork is not available on this platform

Есть ли альтернативное решение для этого в jRuby?

Спасибо.


person Blue Smith    schedule 05.08.2012    source источник
comment
Ответы на этот вопрос могут быть вам полезны.   -  person Sergio Tulentsev    schedule 05.08.2012
comment
Спасибо, Spoon кажется интересным, но не решает мою проблему, потому что просто порождает внешний процесс без совместного использования состояния текущего потока. На самом деле мне нужен «дочерний процесс» — это еще один интерпретатор Ruby, и дочерний процесс будет разделять состояние текущего потока.   -  person Blue Smith    schedule 05.08.2012
comment
@ Ответ Кельвина действительно хорош. Я думаю, что, возможно, стоит спросить, почему вы хотите fork(). Fork() — это системный вызов, встроенный в системы на основе Unix. С другой стороны, Java предназначена для запуска где угодно. Если вам нужно разветвиться, я бы предположил, что JRuby - неправильная реализация ruby ​​​​для вас.   -  person Stewart    schedule 22.04.2015


Ответы (2)


Это хороший вопрос, но, к сожалению, я не верю, что JVM может безопасно дать вам то, что вы хотите, если вы хотите запустить новый процесс, который разделяет состояние с родительским процессом. Это потому, что разветвление копирует только текущий запущенный поток. Например, нити GC не копируются. Вы не хотите запускать JVM без GC.

Единственный полубезопасный способ использования форка — выполнить сразу после него.

Чарльз Наттер в своем блоге сначала говорит, что вы можете использовать FFI для разветвления и выполнения, но затем делает предостережение:

Самая большая проблема с использованием fork+exec таким образом заключается в том, что вы не можете гарантировать, что *ничего* не произойдет между вызовом fork и вызовом exec. Если, например, JVM решит GC или переместить память, вы можете получить фатальный сбой на уровне процесса JVM. Из-за этого я не рекомендую использовать fork + exec через FFI в JRuby, хотя это довольно круто.

Здесь я склонен доверять его совету.

Таким образом, fork и exec сопряжены с некоторым риском, но сохранение разветвленной JVM вызывает проблемы.

Вам следует серьезно рассмотреть альтернативы, предложенные комментарием Серджио.

person Kelvin    schedule 09.11.2012

Я нашел решение для этого. Мы можем использовать встроенную библиотеку FFI в JRuby для «симуляции» Process.fork в 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

Подробнее:

https://github.com/ffi/ffi

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

person Blue Smith    schedule 12.09.2012
comment
Чарльз Наттер предполагает, что разветвлять с помощью jruby опасно, если только вы не собираетесь работать правильно прочь. Выполнение exec приведет к выходу разветвленной JVM, поэтому это безопасно. - person Kelvin; 10.11.2012