なひです. > From: Yukihiro Matsumoto > Sent: Friday, February 26, 1999 3:16 PM なひ: > |> SIGPIPEの方は,ほっとくと / application.commitを通らないので, > |> 溜めたデータがリセットされちゃいますよね... 松尾さん: > |そうなんでしたっけ? SIGKILL(?)以外なら落ちるときでも > |httpserver.initialze の中の、ensureは通ると思ってました。スレッドが異 > |なると駄目なのかなぁ。本当はどうなんでしょう。教えてえらい人。 まつもと ゆきひろさん: > ensureを実行するように作っているつもりだったんですが,通りま ruby 1.2.3(99/02/16) [sparc-solaris2.5.1]を使っています. 簡単なサーバを作って試してみたんですが, やはり親ブロックのensureに制御が移る前に プロセスが死んでいるような気がします. ENDブロックも書いてみましたが,やはり trap( 'SIGPIPE', 'EXIT' ) しておかない限り実行されないようです(あたりまえか... 実際Meeting2000_0_92b1でも, 「新規会合登録」で登録を行なった後, ブラウザのリロードボタンを押しっぱなし攻撃等で サーバを落としてしまうと, 直近60秒の変更はDBに反映されません. # なひがまたなにか勘違いしていないといいんですが... 試したのは以下のサーバです. これを「ruby server.rb &」で起動しておいて, コマンドラインからSIGPIPEを送る(Solaris 2.*ならkill -13 プロセス番号)と, "die..."と表示されずに「Broken pipe ruby server.rb」で戻ってきます. Meeting2000だと,この p "die..." に該当する部分が, @application.commitに相当しますよね? > 松尾さん # 「ここはこう書くのがRuby流」というコメントを歓迎します.(^_^; --- 8< --- 8< ---: 以下はserver.rb require 'SampleSvr.rb' app = SampleSvr.new( 'localhost', 60080 ) --- 8< --- 8< ---: 以下はSampleSvr.rb require 'thread' require 'socket' class SampleSvr private DefaultSvrHostName = 'localhost' DefaultSvrPortNo = 60001 ReadBlockSize = 512 WriteMessage =<<'EOM' HTTP/1.1 200 OK Content-type: text/plain hello world! EOM @svr @hostName @portNo private def initialize( hostName = DefaultSvrHostName, portNo = DefaultSvrPortNo ) begin @hostName = hostName @portNo = portNo p "#{@hostName}##{@portNo}" run resuce p "rescued@initialize" ensure p "die..." end end def run @svr = TCPserver.open( @hostName, @portNo ) while true begin socket = @svr.accept rescue Errno::EPROTO p "Accept failed." next end #p "accepted" Thread.new { acceptHandler( socket ) } end end def acceptHandler( mySocket ) begin mySocket.sysread( ReadBlockSize ) # dummy read mySocket.syswrite( WriteMessage ) rescue Errno::ECONNRESET p "Connection reset by peer" rescue p $! ensure mySocket.close end end end