6

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


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 => trueActiveRecord 连接时才有效,它才能真正连接,这意味着它失去了连接。


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

However, the same is not true with Redis (v2.4.8) which does not lose connection on a fork, again. Does the it try to reconnect internally on a fork?

If thats the case then why isn't the write file program not throwing an error.

Could somebody explain whats going on here. Thanks

4

1 回答 1

4

If you close a file descriptor in one process it stays valid in the other process, this is why your file example works fine.

The mysql case is different because it's a socket with another process at the end. When you call close on the mysql adapter (or when the adapter gets garbage collected when ruby exits) it actually sends a "QUIT" command to the server saying that you're disconnecting, so the server tears down its side of the socket. In general you really don't want to share a mysql connection between two processes - you'll get weird errors depending on whether the two processes are trying to use the socket at the same time.

If closing a redis connection just closes the socket (as opposed to sending a "I'm going away " message to the server) then the child connection should continue to work because the socket won't actually have been closed

于 2012-10-29T10:18:36.913 回答