【问题标题】:Fork, Ruby, ActiveRecord and File Descriptors on ForkFork 上的 Fork、Ruby、ActiveRecord 和文件描述符
【发布时间】:2012-10-16 21:26:10
【问题描述】:

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

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 =&gt 'mysql2', :username =&gt 'root_user', :password =&gt 'Pi', :host =&gt 'localhost', :database => 'list_development', :socket =&gt '/var/lib/mysql/mysql.sock' }) class User &lt 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) 的情况并非如此,它不会再次在分叉上失去连接。它是否尝试在分叉内部重新连接?

如果是这样,那为什么写文件程序没有报错。

有人能解释一下这里发生了什么吗?谢谢

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢弗雷德里克的回答。不确定这是否是一个愚蠢的问题,但请您解释一下“我要走了”消息的含义。
    • 在 mysql 的情况下,客户端实际上发送了一个“QUIT”命令,因此套接字的服务器端关闭套接字,释放任何相关的服务器端资源等。通过“我要走了”,我只是意思是客户端可以发送的命令将导致服务器执行此操作。
    猜你喜欢
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 2011-05-15
    • 1970-01-01
    • 2014-02-15
    • 2012-07-28
    • 2010-09-19
    相关资源
    最近更新 更多