例えばこういうコードをコマンドプロンプト(cmd)から実行すると、server.acceptでブロックした後、CTRL-Cを受け付けなくなってウインドウを閉じるかrubyプロセスをkillするしかないみたい。Windows版の仕様かな。環境はWindows 7(64bit)、ruby 1.9.3p194 (2012-04-20) [i386-mingw32]で確認。
server.acceptも子スレッドから呼び出すようにして、メインスレッドは子スレッドが終了するまでjoinで待つようにしたら大丈夫っぽい。
(2013.4.4追記)
ruby 2.0.0p0 (2013-02-24) [i386-mingw32]では、server.acceptでブロックした後、CTRL-Cを受け付けるようになっていて、無事にスクリプトを停止できました。
require "socket" server = TCPServer.new(21) loop do client = server.accept Thread.new(client) do |cl| begin loop { cl.puts eval cl.gets } rescue ensure cl.close end end end
こんな感じ。
require "socket" server = TCPServer.new(21) Thread.new(server) do |s| loop do client = s.accept Thread.new(client) do |cl| begin loop { cl.puts eval cl.gets } rescue ensure cl.close end end end end (ThreadGroup::Default.list - [Thread.current]).each {|th| th.join} puts "all threads finished"
あと、デフォルトだと子スレッドでエラーが起きても通知されないから
Thread.abort_on_exception = true
も忘れないように。これで通知されます。