1

父进程在一个单独的线程中启动一个 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
4

1 回答 1

0

问题:

孩子复制父亲的记忆和fork的代码。(显然)当你的父亲连接到一些客户端然后产生孩子时,孩子会复制父母的 EM 循环以及它的所有连接对象。当孩子开始新的 EM 循环时,从父亲复制的旧 EM 循环停止,因此所有连接对象都调用“close_connection”。您可能有疑问,为什么在孩子中复制的父亲连接对象会关闭父亲与其客户之间的连接?合理的问题。因为复制的对象仍然拥有与父亲相同的套接字。

解决方案:

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

于 2014-04-28T19:09:52.483 回答