Pergunta

Se eu fizer

Process.fork do 
  x 
end 

Como posso saber o que x retornado (por exemplo true / fase / string)?

(escrita para um arquivo / banco de dados não é uma opção ...)

Foi útil?

Solução 3

I embrulhada todas as soluções I encontrados ao longo do caminho (alguns outros problemas como o utilizador saia de tubagem +-buffers) em rubi gem paralelo. Agora é tão fácil como:

results = Parallel.map([1,2,3],:in_processes=>4) do |i|
  execute_something(i)
end

ou

results = Parallel.map([1,2,3],:in_threads=>4) do |i|
  execute_something(i)
end

Outras dicas

Na verdade, só tinha de lidar com este problema em Rails isolamento testes . Eu postei sobre ele alguma no meu blog .

Basicamente, o que você quer fazer é abrir um canal no pai e criança, e têm a gravação criança ao tubo. Aqui está uma maneira simples de executar o conteúdo de um bloco em um processo filho e voltar o resultado:

def do_in_child
  read, write = IO.pipe

  pid = fork do
    read.close
    result = yield
    Marshal.dump(result, write)
    exit!(0) # skips exit handlers.
  end

  write.close
  result = read.read
  Process.wait(pid)
  raise "child failed" if result.empty?
  Marshal.load(result)
end

Em seguida, você pode executar:

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

Note que se você fizer uma exigem na criança, você não terá acesso a essa biblioteca no pai, então você não pode retornar um objeto desse tipo utilizando este método. No entanto, você pode retornar qualquer tipo que está disponível em ambos.

Observe também que muitos dos detalhes aqui (read.close, Process.wait2(pid)) são na sua maioria arrumação detalhes, por isso, se você usa muito isso você provavelmente deve mover este para fora em uma biblioteca de utilitários que você pode reutilizar.

Finalmente, note que isto não vai funcionar no Windows ou JRuby, uma vez que eles não suportam bifurcação.

Obrigado por todas as respostas, eu tenho a minha solução em funcionamento, ainda precisamos ver como lidar com ambientes sem bifurcação, mas por enquanto ele funciona:)

read, write = IO.pipe
Process.fork do
  write.puts "test"
end
Process.fork do
  write.puts 'test 2'
end

Process.wait
Process.wait

write.close
puts read.read
read.close

Você pode vê-lo em ação @ parallel_specs Rails plugin de

Sim, você pode criar um subprocesso para executar um dentro do bloco.

Eu recomendo o aw gem :

Aw.fork! { 6 * 7 } # => 42

É claro que impede de efeitos colaterais:

arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]

De acordo com a documentação:

Se um bloco for especificado, esse bloco é executado no subprocesso, e os termina subprocesso com um status de zero.

Então, se você chamá-lo com um bloco, ele retorna 0. Caso contrário, ele funciona basicamente o mesmo que a chamada de sistema fork() no Unix (o pai recebe o PID do novo processo, a criança recebe nil).

A comunicação garfo entre dois processos Unix é principalmente o código de retorno e nada mais. No entanto, você poderia abrir uma FileDescriptor entre os dois processos e transmitir dados entre os processos ao longo deste FileDescriptor:. Esta é a maneira normal de tubulação Unix

Se você passaria Marshal.dump () e valores Marshal.load (), você pode facilmente passar objetos Ruby entre esses processos Ruby.

Você pode usar memória compartilhada de fazer isso se a criança só precisa ser um pequeno pedaço de código Ruby. Algo como o seguinte irá funcionar:

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

A concorrência pode ser bastante complicado, embora, e acessando a memória compartilhada desta forma é uma grande parte da razão - a qualquer hora você tem uma variável e outro processo pode alterá-lo debaixo de você, você deve ser muito cauteloso. Alternativamente, você pode usar um tubo, que é mais pesado, mas provavelmente mais seguro para qualquer mas o código mais trivial, e também pode ser usado para executar qualquer comando arbitrária. Aqui está um exemplo, em linha reta do rdoc para IO.popen:

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top