Pregunta

Si lo hago

Process.fork do 
  x 
end 

¿cómo puedo saber qué x Se volvió (por ejemplo, verdadero / fase / cadena)?

(Escribir en un fichero / base de datos no es una opción ...)

¿Fue útil?

Solución 3

Envolví todas las soluciones que he encontrado en el camino (algunos otros problemas como usuario sale + tuberías-buffers) en rubí joya paralelo. Ahora es tan fácil como:

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

o

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

Otros consejos

En realidad sólo tenía que manejar este problema en rieles aislamiento prueba . He publicado algo acerca de ello en mi blog .

Básicamente, lo que se quiere hacer es abrir una tubería en el padre y el niño, y tener el niño escriba a la tubería. Aquí está una manera simple de ejecutar el contenido de un bloque en un proceso hijo y volver el 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

A continuación, puede ejecutar:

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

Tenga en cuenta que si lo hace un requieren en el niño, que no tendrá acceso a la biblioteca de la matriz, por lo que no puede devolver un objeto de ese tipo utilizando este método. Sin embargo, se puede devolver cualquier tipo que está disponible en ambos.

Tenga en cuenta también que muchos de los detalles aquí (read.close, Process.wait2(pid)) son sobre todo los detalles de limpieza, por lo que si se utiliza mucho en esto probablemente debería mover esto hacia fuera en una biblioteca de utilidades que se puede reutilizar.

Por último, tenga en cuenta que esto no funcionará en Windows o JRuby, ya que no son compatibles con la bifurcación.

Gracias por todas las respuestas, tengo mi solución en funcionamiento, todavía necesitan ver cómo manejar entornos no se bifurcan, pero por ahora 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

se puede ver en acción @ parallel_specs rieles complemento

Sí, puede crear un subproceso para ejecutar un bloque interior.

la aw joya :

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

Por supuesto, se impide efectos secundarios:

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

De acuerdo con la documentación:

  

Si se especifica un bloque, este bloque se ejecuta en el subproceso y el subproceso termina con un estado de cero.

Así que si usted lo llama con un bloque, devuelve 0. De lo contrario, funciona básicamente igual que la llamada fork() sistema en Unix (el padre recibe el PID del nuevo proceso, el niño recibe nil) .

La comunicación entre dos procesos tenedor Unix es principalmente el código de retorno y nada más. Sin embargo, se puede abrir un descriptor de fichero entre los dos procesos y pasar los datos entre los procesos a lo largo de este descriptor de fichero:. Esta es la forma normal de la tubería Unix

Si desea pasar Marshal.dump () y Marshal.load () los valores, podría fácilmente pasar objetos de Ruby entre esos procesos Ruby.

Puede usar la memoria compartida para hacer esto si el niño sólo tiene que ser un pequeño trozo de código rubí. Algo así como el siguiente trabajo:

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

La concurrencia puede ser bastante complicado, sin embargo, y el acceso a la memoria compartida de esta manera es una gran parte de la razón - en cualquier momento que tenga una variable y otro proceso puede cambiarlo por debajo de usted, usted debe ser muy cuidadoso. Alternativamente, se puede utilizar un tubo, que es más engorroso, pero probablemente más seguro para cualquier pero el código más trivial, y también se puede utilizar para ejecutar cualquier comando arbitrario. He aquí un ejemplo, directamente de la rdoc para IO.popen:

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top