26

私が行った場合

Process.fork do 
  x 
end 

x が何を返したか (true/fase/string など) を知るにはどうすればよいですか?

(ファイル/データベースへの書き込みはオプションではありません...)

4

7 に答える 7

33

実際には、Rails分離テストでこの問題を処理する必要がありました。私はそれについて私のブログにいくつか投稿しました。

基本的には、親子でパイプを開き、子にパイプに書き込んでもらいます。子プロセスでブロックのコンテンツを実行し、結果を返す簡単な方法は次のとおりです。

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

次に、実行できます。

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

子でrequireを実行すると、親でそのライブラリにアクセスできないため、このメソッドを使用してそのタイプのオブジェクトを返すことはできないことに注意してください。ただし、両方で使用可能な任意のタイプを返すことができます。

また、ここでの詳細の多く(read.closeProcess.wait2(pid))は主にハウスキーピングの詳細であるため、これを頻繁に使用する場合は、再利用できるユーティリティライブラリに移動する必要があります。

最後に、これはWindowsまたはJRubyでは機能しないことに注意してください。これらは、フォークをサポートしていないためです。

于 2009-07-02T20:09:59.650 に答える
12

すべての回答をありがとう、私は自分のソリューションを稼働させましたが、非フォーク環境を処理する方法を確認する必要がありますが、今のところ動作します:)

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

@ parallel_specs Railsプラグインで実際に見ることができます

于 2009-07-02T20:54:34.913 に答える
1

はい、内部でブロックを実行するサブプロセスを作成できます。

私はaw宝石をお勧めします:

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

もちろん、それは副作用を防ぎます:

arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]
于 2015-11-10T17:10:11.613 に答える
0

2つのUnixプロセス間のフォーク通信は、主にリターンコードであり、それ以上のものではありません。ただし、2つのプロセス間でファイル記述子を開き、このファイル記述子を介してプロセス間でデータを渡すことができます。これは通常のUnixパイプ方式です。

Marshal.dump()とMarshal.load()の値を渡す場合は、これらのRubyプロセス間でRubyオブジェクトを簡単に渡すことができます。

于 2009-07-02T19:46:49.090 に答える
0

子がルビーコードの小さなチャンクである必要がある場合は、共有メモリを使用してこれを行うことができます。次のようなものが機能します。

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

ただし、同時実行性にはかなり注意が必要です。この方法で共有メモリにアクセスすることが理由の大きな部分です。変数があり、別のプロセスによって変数が変更される可能性がある場合は、十分に注意する必要があります。または、パイプを使用することもできます。パイプは、より面倒ですが、最も些細なコード以外ではおそらく安全であり、任意のコマンドを実行するためにも使用できます。これは、IO.popenのrdocから直接出た例です。

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
于 2009-07-02T20:06:17.803 に答える
0

ドキュメントによると:

ブロックが指定されている場合、そのブロックはサブプロセスで実行され、サブプロセスはステータス 0 で終了します。

したがって、ブロックで呼び出すと 0 が返されます。それ以外の場合は、基本的fork()に Unix のシステム コールと同じように機能します (親は新しいプロセスの PID を受け取り、子は を受け取りますnil)。

于 2009-07-02T19:37:45.410 に答える