2012-10-26 37 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”命令,以便套接字的服务器端关闭套接字,释放任何关联的服务器端资源等。通过“我要离开”我只是指客户端可以发送的命令这将导致服务器执行此操作。 –