Алтернатива за създаване на процес с „fork“ в jRuby?

В MRI 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
Отговорът на @Kelvin е наистина добър. Мисля, че може би си струва да попитате защо искате да fork(). Fork() е системно повикване, което е вградено в базирани на Unix системи. Java от друга страна е предназначена да се изпълнява навсякъде. Ако трябва да разклоните, бих предложил, че JRuby е грешната реализация на ruby ​​за вас.   -  person Stewart    schedule 22.04.2015


Отговори (2)


Това е добър въпрос, но за съжаление не вярвам, че JVM може безопасно да ви даде това, което искате, ако това, което искате, е да започнете нов процес, който споделя състояние с родителския процес. Това е така, защото разклоняването копира само текущия поток. Нишката(ите) на GC например не се копират. Не искате да работите с JVM без GC.

Единственият полубезопасен начин за използване на вилица е да се изпълни веднага след това.

Чарлз Нътър, в неговия блог, първо казва, че можете да използвате FFI за fork и exec, но след това дава предупреждение:

Най-големият проблем с използването на fork+exec по този начин е, че не можете да гарантирате, че *нищо* няма да се случи между fork call и exec call. Ако, например, JVM реши да GC или да премести паметта, можете да имате фатален срив на ниво JVM процес. Поради това не препоръчвам да използвате fork + exec чрез FFI в JRuby, въпреки че е доста готино.

Тук бих се доверил на съвета му.

И така, разклонението и exec носят известен риск, но поддържането на разклонената JVM изисква проблеми.

Трябва сериозно да обмислите алтернативите, предложени от коментара на Sergio.

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