Question

Si je fais

Process.fork do 
  x 
end 

comment puis-je savoir ce que x est revenu (par exemple vrai / Fase / string)?

(écriture dans un fichier / base de données ne sont pas une option ...)

Était-ce utile?

La solution 3

J'enroulai toutes les solutions que j'ai trouvé le long du chemin (d'autres problèmes comme l'utilisateur sortant + tampons de tuyauterie) dans rubis petit bijou parallèle . Maintenant, il est aussi facile que:

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

Autres conseils

En fait, nous avons eu à gérer ce problème dans test d'isolement Rails . Je posté à ce sujet un peu sur mon blog .

En fait, ce que vous voulez faire est d'ouvrir un tuyau dans le parent et l'enfant, et que l'enfant écrire à la conduite. Voici un moyen simple d'exécuter le contenu d'un bloc dans un processus enfant et retourner le résultat:

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

Ensuite, vous pouvez exécuter:

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

Notez que si vous faites un besoin chez l'enfant, vous n'aurez pas accès à cette bibliothèque dans la société mère, de sorte que vous ne pouvez pas retourner un objet de ce type en utilisant cette méthode. Cependant, vous pouvez revenir tout type qui est disponible dans les deux.

Notez également que beaucoup de détails ici (read.close, Process.wait2(pid)) sont la plupart du temps les détails ménage, donc si vous utilisez ce lot, vous devriez probablement passer ceci dans une bibliothèque utilitaire que vous pouvez réutiliser.

Enfin, notez que cela ne fonctionnera pas sous Windows ou JRuby, car ils ne prennent pas en charge fork.

Merci pour toutes les réponses, je me suis ma solution et en cours d'exécution, doivent encore voir comment gérer des environnements non bifurquent, mais pour l'instant il fonctionne:)

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

vous pouvez le voir en action @ parallel_specs Rails plug-in

Oui, vous pouvez créer un sous-processus pour exécuter un bloc à l'intérieur.

Je recommande le petit bijou aw:

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

Bien sûr, il empêche d'effets secondaires:

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

Selon la documentation:

  

Si un bloc est spécifié, ce bloc est exécuté dans le sous-processus, et le sous-processus se termine par un état de zéro.

Donc, si vous l'appelez avec un bloc, il renvoie 0. Sinon, il fonctionne fondamentalement les mêmes que l'appel système Unix sur fork() (le parent reçoit le PID du nouveau processus, l'enfant reçoit nil) .

La communication de la fourche entre deux processus Unix est principalement le code de retour et rien de plus. Cependant, vous pouvez ouvrir un descripteur de fichier entre les deux processus et transmettre les données entre les processus au cours de cette FileDescriptor. C'est la voie de conduite Unix normale

Si vous transmettre des valeurs Marshal.dump () et Marshal.load (), vous pouvez facilement passer des objets Ruby entre ces processus Ruby.

Vous pouvez utiliser la mémoire partagée pour le faire si l'enfant a juste besoin d'être un petit morceau de code Ruby. Quelque chose comme ce qui suit fonctionnera:

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

Concurrency peut être assez difficile, cependant, et l'accès à la mémoire partagée de cette façon est une grande partie de la raison - chaque fois que vous avez une variable et un autre processus peut changer de sous vous, vous devriez être très prudent. Vous pouvez également utiliser un tuyau, ce qui est plus lourd, mais sans doute plus sûr pour tout mais le code le plus trivial, et peut également être utilisé pour exécuter une commande arbitraire. Voici un exemple, tout droit sorti de la rdoc pour IO.popen:

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top