2012-10-26 21 views
6

我明白,當我們分叉一個進程時,子進程會繼承父級打開文件描述符和偏移量的副本。根據手冊頁,這指的是父級使用的相同文件描述符。基於這一理論在下面的程序Fork上的叉子,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在這種情況下如何失去連接。它只適用於如果我設置:reconnect => true上的ActiveRecord連接它可以實際連接,這意味着其失去連接。

 

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

如果您在一個進程中關閉文件描述符,它在其他進程中保持有效,這就是爲什麼您的文件示例工作正常。

mysql的情況是不同的,因爲它是一個套接字與最後的另一個進程。當你在mysql適配器上調用close時(或者當適配器在ruby退出時得到垃圾回收)時,它實際上會向服務器發送一個「QUIT」命令,表示你正在斷開連接,所以服務器會關閉它的插槽。一般來說,你真的不想在兩個進程之間共享一個mysql連接 - 你會得到奇怪的錯誤,這取決於這兩個進程是否嘗試同時使用套接字。

如果關閉redis連接只是關閉套接字(而不是發送「我要離開」消息到服務器),那麼子連接應該繼續工作,因爲套接字實際上並沒有關閉

+0

謝謝你的答案弗雷德裏克。不確定這是否是一個愚蠢的問題,但請你解釋一下「我要走了」的信息是什麼意思。 – Sid

+0

在mysql的情況下,客戶端實際上發送一個「QUIT」命令,以便套接字的服務器端關閉套接字,釋放任何關聯的服務器端資源等。通過「我要離開」我只是指客戶端可以發送的命令這將導致服務器執行此操作。 –