2012-10-26 5 views
6

私は、プロセスをフォークするとき、子プロセスは、親のファイルのディスクリプタとオフセットのコピーを継承することを理解します。マニュアルページによると、これは親によって使用されるのと同じファイル記述子を参照します。次のプログラムではその理論に基づいてフォークのRuby、Ruby、ActiveRecord、およびファイル記述子

 

puts "Process #{Process.pid}" 

file = File.open('sample', 'w') 

forked_pid = fork do 
    sleep(10) 
    puts "Writing to file now..." 
    file.puts("Hello World. #{Time.now}")  
end 




file.puts("Welcome to winter of my discontent #{Time.now}") 
file.close 
file = nil 
 

質問1: は10秒間眠っているフォークプロセスがそのファイル記述子を失うことはありませんし、親プロセスとしてファイルに書き込みできないようにする必要があり完了してファイルを閉じて終了します。
質問2:しかし、何らかの理由でこれが機能する場合、ActiveRecordはこのシナリオでどのように接続を失いますか? ActiveRecord connectで実際に接続できるのは、:reconnect => trueに設定した場合のみです。つまり、接続が失われていることを意味します。

 

require "rubygems" 
require "redis" 
require 'active_record' 
require 'mysql2' 

connection = ActiveRecord::Base.establish_connection({ 
    :adapter => 'mysql2', 
    :username => 'root_user', 
    :password => 'Pi', 
    :host => 'localhost', 
    :database => 'list_development', 
    :socket => '/var/lib/mysql/mysql.sock' 

    }) 

class User < ActiveRecord::Base 
end 

u = User.first 

puts u.inspect 

fork do 
    sleep 3 
    puts "*" * 50 
    puts User.first.inspect 
    puts "*" * 50 

end 

puts User.first.inspect 
 

ただし、フォーク上の接続が失われないRedis(v2.4.8)でも同じことが繰り返されます。フォーク上で内部的に再接続しようとしていますか?

その場合、なぜ書き込みファイルプログラムがエラーをスローしないのでしょうか。

誰かがここで何が起こっているのか説明できますか?ありがとう

答えて

4

1つのプロセスでファイル記述子を閉じると、他のプロセスで有効なままであるため、ファイルの例は正常に動作します。

mysqlのケースは、別のプロセスが最後にあるソケットであるため、ケースが異なります。 mysqlアダプタでcloseを呼び出すと(またはrubyが終了したときにアダプタがガベージコレクトされると)、実際に切断していることを示す「QUIT」コマンドがサーバに送信され、サーバはソケットの側面を裂きます。一般に、2つのプロセス間でmysql接続を共有したくない場合、2つのプロセスが同時にソケットを使用しようとしているかどうかによって、奇妙なエラーが発生します。

レディス接続を閉じると、ソケットが閉じられるだけです(サーバーに「I'm going away」メッセージを送信するのとは対照的です)。ソケットが実際に閉じられていないため、子接続は引き続き機能します。

+0

答えフレデリックに感謝します。これが愚かな質問であるかどうかは分かりませんが、「私は去っていく」というメッセージの意味を説明してください。 – Sid

+0

mysqlの場合、クライアントは実際には "QUIT"コマンドを送信して、ソケットのサーバー側がソケットを閉じ、関連するサーバー側リソースなどを解放します。 '私は離れます'という意味では、サーバーがこれを行う原因になります。 –

関連する問題