Fork上的Fork,Ruby,ActiveRecord和文件描述符

时间:2012-10-26 15:28:31

标签: ruby-on-rails ruby activerecord fork file-descriptor

据我所知,当我们分叉一个进程时,子进程会继承父进程打开文件描述符和偏移量的副本。根据手册页,这指的是父母使用的相同文件描述符。基于以下程序中的理论


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上设置: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),它不会再失去连接上的连接。它是否尝试在fork上进行内部重新连接?

如果是这样,那么为什么写文件程序不会抛出错误。

有人可以解释这里发生的事情吗?感谢

1 个答案:

答案 0 :(得分:4)

如果您在一个进程中关闭文件描述符,它在另一个进程中保持有效,这就是您的文件示例正常工作的原因。

mysql的情况有所不同,因为它是一个套接字,最后有另一个进程。当你在mysql适配器上调用close时(或当ruby退出时适配器被垃圾收集)它实际上向服务器发送一个“QUIT”命令,说你正在断开连接,所以服务器拆掉了它的插槽侧面。一般来说,你真的不想在两个进程之间共享一个mysql连接 - 你会得到奇怪的错误,这取决于两个进程是否同时尝试使用套接字。

如果关闭redis连接只是关闭套接字(而不是向服务器发送“我正在离开”消息),那么子连接应继续工作,因为套接字实际上不会被关闭