Server program を Thread に頼らず作る
訳あって、Server program を Thread に頼らず、fork を使って作ってみることにした。
#!/usr/bin/env ruby require "socket" require 'time' Signal.trap('CHLD') do puts "waiting" Process.waitall end print $$.to_s + ": parent pid\n" accepter = TCPserver.open(12345) loop do io = accepter.accept fork do io.write(Time.now.iso8601 + "\n") io.close print $$.to_s + ": child pid after fork\n" exit!(0) end io.close print $$.to_s + ": parent pid after fork\n" end
ポイントは 2 つ。
- socket は子プロセス側だけではなく、親プロセス側も close すること。そうでないと、クライアント側からみて、切断がされない。
- シグナル SIGCHLD に Process.wait を実行する trap を仕掛けること。そうでないと、ゾンビプロセスを看取ることができない(=ゾンビが残る状態になる)
後者についてはこれまで良く理解していなかった。15年ぐらい前に C で作った Server program はたぶんこの問題の影響か、数日稼働すると停止するという困った動きをしてくれていた。