[#45311] 開発会議 — SASADA Koichi <ko1@...>
笹田です.
10 messages
2012/03/06
[#45312] Re: 開発会議
— "ayumu.aizawa@..." <ayumu.aizawa@...>
2012/03/06
US=1B$B$K$$$k$N$G!"=1B(BSkype=1B$B$H$+=1B(BFaceTime=1B$B$G;22C$7$?$$$G$9!#=1B=
[#45341] 非同期割り込みに対する対処案(日本語版) — SASADA Koichi <ko1@...>
ささだです.
28 messages
2012/03/11
[#45816] Re: 非同期割り込みに対する対処案(日本語版)
— SASADA Koichi <ko1@...>
2012/06/25
ささだです.
[#45817] Re: 非同期割り込みに対する対処案(日本語版)
— Tanaka Akira <akr@...>
2012/06/25
2012年6月25日 18:26 SASADA Koichi <ko1@atdot.net>:
[#45819] Re: 非同期割り込みに対する対処案(日本語版)
— SASADA Koichi <ko1@...>
2012/06/25
ささだです.
[#45820] Re: 非同期割り込みに対する対処案(日本語版)
— Tanaka Akira <akr@...>
2012/06/25
2012年6月25日 19:39 SASADA Koichi <ko1@atdot.net>:
[#45827] Re: 非同期割り込みに対する対処案(日本語版)
— SASADA Koichi <ko1@...>
2012/06/25
(2012/06/25 20:32), Tanaka Akira wrote:
[#45835] Re: 非同期割り込みに対する対処案(日本語版)
— KOSAKI Motohiro <kosaki.motohiro@...>
2012/06/25
> の3つになるような気がしていますので,ある例外がこれら 3 つのどの状態に
[#45841] Re: 非同期割り込みに対する対処案(日本語版)
— Tanaka Akira <akr@...>
2012/06/25
2012年6月26日 3:40 SASADA Koichi <ko1@atdot.net>:
[#45844] Re: 非同期割り込みに対する対処案(日本語版)
— SASADA Koichi <ko1@...>
2012/06/25
(2012/06/26 5:07), Tanaka Akira wrote:
[#45871] Re: 非同期割り込みに対する対処案(日本語版)
— Tanaka Akira <akr@...>
2012/06/29
2012年6月26日 5:15 SASADA Koichi <ko1@atdot.net>:
[#45372] Marshal.dumpにおけるインスタンス変数の取り扱いについて — keiju@... (Keiju ISHITSUKA)
けいじゅ@いしつかです.
14 messages
2012/03/16
[#45376] Re: Marshal.dumpにおけるインスタンス変数の取り扱いについて
— Yukihiro Matsumoto <matz@...>
2012/03/17
まつもと ゆきひろです
[#45377] Re: Marshal.dumpにおけるインスタンス変数の取り扱いについて
— keiju@... (石塚圭樹)
2012/03/17
けいじゅ@いしつかです.
[#45381] Re: Marshal.dumpにおけるインスタンス変数の取り扱いについて
— Yukihiro Matsumoto <matz@...>
2012/03/17
まつもと ゆきひろです
[#45399] Re: Marshal.dumpにおけるインスタンス変数の取り扱いについて
— keiju@... (石塚圭樹)
2012/03/18
けいじゅ@いしつかです.
[#45401] Re: Marshal.dumpにおけるインスタンス変数の取り扱いについて
— Tanaka Akira <akr@...>
2012/03/19
2012年3月19日5:54 石塚圭樹 <keiju@ishitsuka.com>:
[#45405] Re: Marshal.dumpにおけるインスタンス変数の取り扱いについて
— keiju@... (石塚圭樹)
2012/03/19
けいじゅ@いしつかです.
[#45451] [ruby-trunk - Feature #6218][Open] struct.cのrb_struct_s_members_m()について — "Glass_saga (Masaki Matsushita)" <glass.saga@...>
6 messages
2012/03/28
[ruby-dev:45341] 非同期割り込みに対する対処案(日本語版)
From:
SASADA Koichi <ko1@...>
Date:
2012-03-11 11:35:14 UTC
List:
ruby-dev #45341
ささだです.
開発会議で出た「非同期割り込みがこの先生き残るには」という議論を,とり
あえず日本語でまとめました.まだあまりまとまっていない(すみません)の
で,すみませんが日本語で出させて下さい&突っ込んで下さい.
あとで英語化したいと思います(してくれると嬉しい).英語化できたら,今
後はそっちということで.
用語:
・trap ハンドラ:trapで登録するシグナルが来たときに行うブロック
trap(SIGINT){ ... } の ... 部分
・非同期割り込み:Thread#raise や trap ハンドラなど,意図しない
イベントを,ここでは非同期割り込みと呼ぶ
(他にもあったら教えて下さい)
・割り込みチェック:非同期例外があるかどうかチェックし,もしあれば
例外を発生刺せたり trap ハンドラを実行したりする
・ブロッキング処理:I/O などで,ブロックするかもしれない処理.
概要:
非同期割り込みをチェックするタイミングを制御する primitive を提供す
る.制御の種類は次の通り,
0. なるべく頻繁にチェックする(これまで通りの動作)
1. ブロッキング処理のタイミングだけチェックする
2. チェックしない
ただし.チェックする例外クラス(の祖先)は指定できる.
なので,SignalException (を継承した Interrupt)は頻繁にチェックする,
すなわち Ctrl+C はだいたい効く,しかし,TimeoutError のような例外は安全
なところまで遅延して処理するといった挙動が容易に記述できる.
背景:
Thread#raise を使うと,スレッドに対していろんなちょっかいを出すことが
できる.また,trap(signal){...} とすると,任意のシグナルについて対応する
ことができる.
# 例1
th = Thread.new{
begin
...
rescue NantokaError
...
end
}
th.raise(NantokaError) #=> th に NantokaError を強制的に引き起こす
# 例2
q = Queue.new
th1 = Thread.new{
q << calc_in_algorithm1
}
th2 = Thread.new{
q << calc_in_algorithm2
}
result = q.pop
th1.raise(TerminateCalcError)
th2.raise(TerminateCalcError)
# アルゴリズム1,2 で計算して,どちらか先に答えが出たら,
# もう1つのほうを止める
# 例3
trap(SIGINT){
# 何か後処理
}
trap(SIGHUP){
# 何か reload 処理
}
server_exec # サーバの処理
なお,現在の割り込みチェックは,RUBY_VM_CHECK_INTS() で行っており,メ
ソッドの起動時,リターン時,前方へのジャンプ時,ブロッキング処理の前後で
行っている.
問題点:
Thread#raise だとかが上がってくるタイミングは制御できないので,例えば
ensure 中で後処理をしていた場合に困る.
例えば,例4 は timeout の実装(の簡略版)ですが,yield で起動したブ
ロック中で,ensure を用いて何か資源の後始末をしていたとしても,その後始
末中に(ensure 節実行中に)TimeoutError が発生してしまう可能性がある.
# 例4
def timeout(sec)
timer_thread = Thread.new(Thread.current){|parent|
sleep(sec)
parent.raise(TimeoutError)
}
begin
yield
ensure
timer_thread.stop # close thread
end
end
timeout(3){
begin
f = open(...) # open(...){|f| ...} でいいんだけど,まぁ例として
ensure
f.close
end
}
では,ensure だけでいいのか,というと,それ以外にも問題がある.例えば
次に示す例5について考える.
# 例5
begin
f = open(...)
ensure
f.close if f
end
open(...) で開いたものを,"f =" でローカル変数に代入が完了する前に割り
込まれたとき,f は nil のままなので ensure で close されない.この例の
File の場合は GC で閉じることも可能だが,解放を必須とする資源一般を考え
ると問題である.
この点について,例えば,行末まで割り込みを許さない(行末だけチェックす
る),といった解決案も提案されたが,"f =" や "open(...)" がもっと複雑
だった場合,その解決では無理である(例えば,"foo.bar =" は複数行のメソッ
ドの場合がある).
提案:
非同期割り込みをチェックするタイミングを制御するための仕組みを新設す
る.原案は [1] にあるとおり.ただ,名前については今後検討する.
制御の種類は次の通り,
0. なるべく頻繁にチェックする(これまで通りの動作)
1. ブロック I/O のタイミングだけチェックする
2. チェックしない
0 はこれまで通り.
1 は,POSIX thread の cancellation point らしい.長時間ブロックする処
理は Thread#raise やシグナルでキャンセルすることが可能.
2 は,一切チェックしない.完全に非同期割り込みセーフに処理することが可能.
ただし.チェックする例外クラス(の祖先)は指定できるようにする.これに
より,例えば SignalException (を継承した Interrupt)は頻繁にチェックす
る,すなわち Ctrl+C はだいたい効く,しかし,TimeoutError のような例外は
安全なところまで遅延して処理するといった挙動が容易に記述できる.
議論:
・デフォルトをどのモード(前節 0〜2 のこと)にするか?
・モード 1 で困る人はどれくらいいるか?
(いないならデフォルトこれでいいんでは?)
・計算スレッドは止めても困らないので,例2のような場合はこれまで
通り止めたい,という,モード 0 を期待する例はある.
・ensure 実行時に自動的にモードを変更するか?
※ええと,すみません,いろんな議論があったと思いましたが,誰か補完して下
さい....
余談(というか TODO):
rb_blocking_region() 時に強制的に終了時に CHECK_INTS() しているのはけ
しからんので,CHECK_INTS() を呼び出し側でさせるバージョンを作るべきである.
例えば,
blocking_region{
data = read(...)
}
とあったとき,data が到達しているのならば,割り込んで欲しくないはずで
ある.ただし,data が到達する前に割り込みで中断していれば,CHECK_INTS()
により例外を発生させるべきである.この判断は rb_bocking_region() 利用者
しかできないので,その判断をさせるべきである.
参考文献:
[1] Akira Tanaka "Re: Thread#raise, Thread#kill, and timeout.rb are
unsafe" ruty-talk (2008.3)
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/294917
謝辞:
この議論は,3/11 10:00から開催されたRuby開発者会議で行われました.参加
者は田中さん,nahi さん,たるいさん,mrkn さん,skype 越しに小崎さん,中
田さん,sora さん,遠藤さんでした.朝もはよからありがとうございました.
--
// SASADA Koichi at atdot dot net