[#43353] 丸数字の文字コード変換 — Masuda Yoshihisa <sacong@...>
マスダといいます。
10 messages
2007/04/02
[#43363] 特定のmoduleに属しているかの判別 — "西塔伸一郎" <sinsaihy@...>
初めまして
5 messages
2007/04/04
[#43369] dRuby に CGI を渡す→script_uri が上手く取得出来ない — 石井 大海 <banzaida@...>
こんばんは、konnです。
10 messages
2007/04/05
[#43373] Re: dRuby に CGI を渡す→script_uri が上手く取得出来ない
— Masatoshi SEKI <m_seki@...>
2007/04/06
咳といいます。
[#43374] Re: dRuby に CGI を渡す→script_uri が上手く取得出来ない
— 石井 大海 <banzaida@...>
2007/04/06
こんにちは、konnです。
[#43376] Re: dRuby に CGI を渡す→script_uri が上手く取得出来ない
— Masatoshi SEKI <m_seki@...>
2007/04/06
咳といいます。
[#43382] VB6からrubyを呼び出す際の問題について — "takumi iino" <trot.thunder@...>
はじめまして。飯野と申します。
11 messages
2007/04/06
[#43383] Re: VB6からrubyを呼び出す際の問題について
— rubikitch@...
2007/04/06
From: "takumi iino" <trot.thunder@gmail.com>
[#43384] Re: VB6からrubyを呼び出す際の問題について
— "takumi iino" <trot.thunder@...>
2007/04/06
飯野です。
[#43385] Re: VB6からrubyを呼び出す際の問題について
— "takumi iino" <trot.thunder@...>
2007/04/06
飯野です。
[#43407] オブジェクトのインスタンス変数名の取得 — pegacorn <subscriber.jp@...>
こんにちは。
8 messages
2007/04/10
[#43408] Re: オブジェクトのインスタンス変数名の取得
— Yukihiro Matsumoto <matz@...>
2007/04/10
まつもと ゆきひろです
[#43409] Re: オブジェクトのインスタンス変数名の取得
— pegacorn <subscriber.jp@...>
2007/04/10
07/04/10 に Yukihiro Matsumoto <matz@ruby-lang.org> さんは書きました:
[#43410] Re: オブジェクトのインスタンス変数名の取得
— Yukihiro Matsumoto <matz@...>
2007/04/10
まつもと ゆきひろです
[#43415] Gtk::TreeView でドラッグ — Takeshi Honda <moecho21@...>
お世話になります。
5 messages
2007/04/10
[#43428] ClassのクラスはClass自身でない? (RHGの疑問点) — Yoshino <ysnmin@...>
初めまして。吉野と言います。
5 messages
2007/04/12
[#43435] ruby から C/C++ の利用法 — ohrsts@...
小原と申します。
6 messages
2007/04/14
[#43450] Fwd: 「オープンソースカンファレンス2007 Hokkaido」開催のお知らせ — "SHIMADA Koji" <snoozer.05@...>
しまだ@Ruby札幌です。
4 messages
2007/04/20
[ruby-list:43356] TCPSocket#flushでスレッドが停止する現象について
From:
"KOSEKI Kengo" <kengo@...>
Date:
2007-04-02 09:20:17 UTC
List:
ruby-list #43356
はじめまして。
小関と申します。
Rails + MySQLを使っていて、長時間DBへのアクセスが無い場合に
Railsアプリケーションが反応しなくなる問題を調べています。
MongrelのFAQでそれらしい現象が報告されているのですが、
http://mongrel.rubyforge.org/faq.html
> Q: Mongrel stops working if it's left alone for a long time.
ここに載っている対策は以下の点で正しくないのではないかと
考えています。
* ソースを読むと、ActiveRecord::Base.verification_timeout は
接続確認を「行わない」期間を表す値に見える。
* RailsとMySQL間の接続のタイムアウトは、interactive_timeoutで
はなく、wait_timeoutで設定するのでは。
* 少なくとも手元の環境では問題が解決しなかった。
いろいろ試した結果、Railsを使わずに、以下の手順で原因と
思われる症状を再現できました。
----------------------------------------------------------------
1. TCPSocketを、SO_KEEPALIVEソケットオプションをオンで作成。
2. 別のスレッドを起動する。このスレッドはsleepしているだけでOK。
3. サーバから接続をcloseする。
4. クライアントはcloseせず、CLOSE_WAITが消えるまで待つ。
5. その後2回TCPSocket#flushを実行。
6. 1回目のflushはBroken pipeの例外が発生する。
7. 2度目flushの実行中にスレッドが停止したままになる。
----------------------------------------------------------------
上記2.で、別のスレッドを起動しなかった場合は再現しませんでした。
でした。また、4.のCLOSE_WAITが消える前でも、再現しませんでした。
Railsでは、3.がwait_timeoutの切断に相当し、5.の2回のflushが
mysql.rbドライバのCOM_STATISTICS/COM_QUIT送信に相当します。
Rubyのソースにプリント文を入れてどこで止まっているのか確認した
ところ、io.cのio_fflushから呼ばれる、
eval.c rb_thread_fd_writable(fd)内の、
rb_thread_schedule()で停止しているようでした。
http://www.tamacom.com/tour/lang/ruby/S/43.html#L346
http://www.tamacom.com/tour/lang/ruby/S/35.html#L10795
あまりよくわかっていませんが、
curr_thread->wait_for = WAIT_SELECT;
が満たされないので、flushを実行中のスレッドに制御が移らなく
なるのではないかと思います。
これはRuby本体の問題のような気がするのですが、
どうでしょうか?
以下具体的な再現の手順です。
■サーバ (sv.rb) - TCPServerのサンプルほぼそのままです。
---------------------------------------------------------
#! /usr/bin/env ruby
require "socket"
port = ARGV[0]
puts "server[#{$$}]: #{port}"
puts Time.new.to_s
gs = TCPServer.open(port)
while true
Thread.start(gs.accept) do |s|
print(s, " is accepted\n")
while s.gets
puts $_
end
print(s, " is gone\n")
s.close
end
end
---------------------------------------------------------
■クライアント (cl.rb)
---------------------------------------------------------
#! /usr/bin/env ruby
require "socket"
def start_another_thread
@th = Thread.new do
while true do
sleep 5
end
end
puts "Thread started: #{@th}"
end
def connect(host, port)
STDOUT.sync = true
@sock = TCPSocket.open(host, port)
@sock.setsockopt Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true
end
def flush
begin
@sock.sync = false
@sock.write("client[#{$$}]: write " + Time.new.to_s + "\n")
@sock.sync = true
puts "--- BEGIN flush"
@sock.flush
puts "--- END flush"
rescue => e
puts "rescue: #{e}"
end
end
Signal.trap(:QUIT) do
5.times { do_flush }
end
#
# main
#
(host,port,wait) = ARGV
wait = wait.to_i
wait = 150 if wait <= 0
puts "client[#{$$}]: #{host}:#{port} wait:#{wait}sec"
puts Time.new.to_s
if 3 < ARGV.length
start_another_thread
end
connect(host, port)
flush
while true
print "--- sleep "
i = 0
(wait / 10).times do
print "#{i += 1}."
sleep 10
end
puts
5.times { flush }
end
@sock.close
---------------------------------------------------------
■ 再現の手順
0. ターミナルを3つ開く。
1. サーバを10080番ポートで起動。
$ ./sv.rb 10080
2. クライアントを起動。
$ ./cl.rb localhost 10080 7800 1
7800秒後にflushする。末尾の1は別スレッドを起動する指定。
3. netstatのFIN_WAITとrubyを監視。
$ watch -n1 'netstat -nap 2> /dev/null | grep "\(FIN_WAIT\|ruby\)"'
4. 実行中のサーバをC-cで止める。
5. FIN_WAIT2が約1分後に消えるのを確認する。
6. CLOSE_WAITが約2時間後に消えるのを確認する。
7. クライアントが7800秒後に以下を出力して止まる。
--- BEGIN flush
rescue: Broken pipe
--- BEGIN flush
cl.rbの起動オプションで末尾の1を指定しなかった場合は、
別のスレッドが起動せず、5回繰り返しBroken pipeが表示される。
--- BEGIN flush
rescue: Broken pipe
--- BEGIN flush
rescue: Broken pipe
--- BEGIN flush
rescue: Broken pipe
--- BEGIN flush
rescue: Broken pipe
--- BEGIN flush
rescue: Broken pipe
CLOSE_WAITが消えるまでの2時間の待ち時間は、以下の
設定で短縮できる(システム全体の設定が変わるので注意が必要)。
# echo 30 > /proc/sys/net/ipv4/tcp_keepalive_time
# echo 20 > /proc/sys/net/ipv4/tcp_keepalive_intvl
cl.rbの起動オプションは、7800の代わりに150を指定する。
150秒で再現する。
■環境
VMWare上のFedora FC5
# ruby --version
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]
以上よろしくお願いいたします。
--
koseki - http://d.hatena.ne.jp/koseki2/