当具有另一个EventMachine实例的子进程被终止时,EventMachine将断开连接的客户端

时间:2013-01-30 06:14:37

标签: ruby multithreading fork eventmachine

父进程在一个单独的线程中启动一个EventMachine服务器,并在主线程中监视并重新生成死工作者。

子进程启动另一个EventMachine服务器,然后在五秒后退出。

问题是,当新子节点启动时,父进程的所有连接客户端都将断开连接。

我有什么办法可以做到这一点吗?

require 'eventmachine'

module EchoServer
  def post_init
    puts "-- someone connected to the echo server!"
  end

  def receive_data data
    send_data ">>>you sent: #{data}"
    close_connection if data =~ /quit/i
  end

  def unbind
    puts "-- someone disconnected from the echo server!"
  end
end

puts "Forking..."

def start_echo_server
  Thread.new {
    puts "Starting Echo server"

    EventMachine.run {
      EventMachine.start_server "127.0.0.1", 8081, EchoServer
    }
  }
end

def spawn_workers
  if @pid = fork
    @started = start_echo_server unless @started
  else
    puts "Child #{$$}: Sleeping for 5 seconds"
    EventMachine.run {
      EventMachine.start_server "127.0.0.1", 8082, EchoServer
      EventMachine.add_timer(5) do
        puts "Child #{$$}: exiting..."
        exit
      end
    }
  end

  @pid
end

spawn_workers

if @pid
  begin
    # check if we have any child process that died
    wpid, status = Process.waitpid2(-1, Process::WNOHANG)
    wpid or (sleep 0.1 && next)
    spawn_workers

  rescue Errno::ECHILD
    break
  end while true
end

1 个答案:

答案 0 :(得分:0)

问题:

Child复制父亲的记忆和代码。 (明显) 当您的父亲连接到某些客户端然后生成子项时,子项复制父项的EM循环及其所有“连接对象”。 当子进程启动新的EM循环时,从父进程复制的旧EM循环停止,因此所有连接对象都调用“close_connection”。你可能有问题为什么父亲连接对象复制在子关闭父亲和它的'客户端之间的连接?合理的问题。因为复制的对象仍然保持与父亲相同的套接字。

解决方案:

在您在孩子中调用EM.run之前,请在当前新生成的子项中从父派生的所有连接对象上调用“detach”。 “detach”会将子连接对象从套接字(父客户端)中分离出来,并阻止子进程关闭该套接字。