In article <871y5j...@studly.priv.netlab.jp>
Shugo Maeda <sh...@ruby-lang.org> writes:
> 前田です。
> そういえば、昔まつもとさんにRubyで
> thread.kill
> でスレッドを強制終了できるようにしてほしい(当時は
> Thread.kill(thread)のようにクラスメソッドを使わないといけませんで
> した)とたのんだ時に、「threadが主語であるべきだからkillはおかしい」
> と却下されました。
文法はどちらでもいいですが、スレッドを強制終了するのは、ロッ
クの関係で危険だということで、POSIX Threads には入っていませ
ん。pthread_kill() は、割込みをかけるものです。(割込みもス
レッドと合わないからやめた方がいいとおもうけれど。)
POSIX Threads には、スレッドを止めるのに pthread_cancel() と
いう機能はあります。これは、スレッドに自発的に死ぬようにとメッ
セージを送るだけで、実際にはスレッドは直ぐには死にません。普
通は、cancellation point にたどり着いた時に調べて、cancel が
かかっていれば、死にます。
なんでこうしたかというと、ロックを保持したままスレッドが死ん
だらどうなるのかという問題があって、それを何とかしようとして
任意の場所ではだめでも、特定の場所ならいいんじゃないかという
ことで入れたのでしょう。ただ、本当にこの cancel 機能がうまく
使われているのかは、不明です。私は一度も使ったことがありません。
Java で stop() がなくなったのは、同じ事情だと思います。
native のスレッドと対応させる時には、問題が出てくるのでしょう。
> # 実はその後いつの間にか取りこまれてて今のRubyでは使えるんですが。
Ruby で、ロックを保持したスレッドが殺されるとどうなるんでしょ
うか?
Perl は、どうなんでしょうか?
オブジェクト指向とは関係ないので、
Followup-To: fj.comp.parallel,fj.comp.lang.misc
としてみました。
\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報 \\
y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes:
|Ruby で、ロックを保持したスレッドが殺されるとどうなるんでしょ
|うか?
面倒なことになります。ただ、RubyのMutexにはsynchronizeってメ
ソッドがあって、
mutex.synchronize do
..排他したい処理..
end
という風に書けるのですが、この場合にはkillされてもロックは解
除されます。そのはずです。
> mutex.synchronize do
> ..排他したい処理..
> end
>
> という風に書けるのですが、この場合にはkillされてもロックは解
> 除されます。そのはずです。
共有資源が一貫しない状態にあるときにロックが解除されても、それはそれで
困るんですよね。やっぱり殺すのって難しい。
前田敦司
In article <m3n0nws...@maedapc.cc.tsukuba.ac.jp>
MAEDA Atusi <ma...@cc.tsukuba.ac.jp> writes:
> 共有資源が一貫しない状態にあるときにロックが解除されても、それはそれで
> 困るんですよね。やっぱり殺すのって難しい。
逆に、どうい時にスレッドを殺しても平気かを考えてみました。
・スレッドがロックを持ってない時
・トランザクションがちゃんと実現できている時
他にありますか?
昨日、通信のプログラムで時間切れの処理を書きたくて、Cで、
fork() するプログラムを書きました。時間が来ても exit() して
なければ、kill() します。スレッドでは、書けなくて。プロセス
なら、kill() して全部チャラにできるので、一種のトランザクショ
ンのようなものです。
時間切れというと、Ruby でこんなプログラムを見たなあ。
timeout (20) do
Net::SMTP.start( email_server ) do |session|
session.send_mail( text, from, to )
end
end
どうしているんでしょうね。中で作った socket を閉じたりする辺
り。昨日書いたCのプログラムだと fork() しているので子プロセ
スごとチャラになるのはいいとして、子供から親につながった
socket を渡そうとすると、一大事です。昨日は必要なかったけれ
ど。sendmsg() でできたはず。あ、新しい BSD や Linux で方法が
違ってますね。昔は、msghdr に msg_accrights というのがありま
した。最近は、msg_control で、SCM_RIGHTS でいいのかな。
JavaSpaces とか .NET にトランザクションが入っているんですけ
ど、あんなの本当に「提供」できるんですかね。「利用」する方か
らすると、便利そうなんだけど。
> 逆に、どうい時にスレッドを殺しても平気かを考えてみました。
>
> ・スレッドがロックを持ってない時
> ・トランザクションがちゃんと実現できている時
>
> 他にありますか?
最近、とあるアプリケーション(TCP の port forwarder)を書いたときに、ス
レッドを殺さざるを得なくて、はたして殺しても大丈夫なのかどうか考える機
会がありました。
port forwarder なんで、ソケットが 2つあって、2つのスレッドがそれぞれ上
りと下りのデータ転送をしています。で、どちらかのスレッドでエラー(RST
の到着による ECONNRESET)が検出されたら即座に全体を終了させたいんですが、
もう一方のスレッドが(エラーが出なかったほうのソケットで) IO 待ちをして
いる可能性があります。その場合、待っている間は自殺できないので、他のス
レッドが殺さざるを得ません。
(Ruby で書いたんですが、少なくとも Ruby のスレッドでは IO 待ちの途中で
自殺することはできないと思う。)
この話をどうロックやトランザクションに対応させられるのかはよくわかんな
いんですが、まぁ、片方のソケットが RST で死んだらどーせ処理は続けられ
ないんだし殺しても問題なかろう、と思いました。
> 時間切れというと、Ruby でこんなプログラムを見たなあ。
>
> timeout (20) do
> Net::SMTP.start( email_server ) do |session|
> session.send_mail( text, from, to )
> end
> end
>
> どうしているんでしょうね。中で作った socket を閉じたりする辺
> り。
閉じるだけならどうにでもなるんじゃないかなぁ。
> 昨日書いたCのプログラムだと fork() しているので子プロセ
> スごとチャラになるのはいいとして、子供から親につながった
> socket を渡そうとすると、一大事です。昨日は必要なかったけれ
> ど。sendmsg() でできたはず。あ、新しい BSD や Linux で方法が
> 違ってますね。昔は、msghdr に msg_accrights というのがありま
> した。最近は、msg_control で、SCM_RIGHTS でいいのかな。
前に書いたことがあります。その結果は Ruby 1.7 に入っているので
% echo foo > foo
% ruby -rsocket -e '
s1,s2 = UNIXSocket.socketpair
fork {
s2.send_io(open("foo"))
}
f = s1.recv_io
p f.read
'
"foo\n"
とかできたりします。まぁ、実装は 2種類でいいのでそれほど厄介ではなかっ
たですね。
(SCM_CREDS の類は 2種類どころでは済まないので手をつけかねてますが...)
--
[田中 哲][たなか あきら][Tanaka Akira]
「ふえろ! わかめちゃん作戦です⊇」(Little Worker, 桂遊生丸)
MAEDA Atusi <ma...@cc.tsukuba.ac.jp> writes:
同意します。やはり殺すことにはそれなりにリスクが伴うのでは。
「まずい*かもしれない*から殺さない」というのは現実世界では当
然の戦略ですが、「まずくないようにしてから殺す(まずいことが
起きたら自己責任)」というのが、ソフトウェア的なやり方なのか
なあ。単なるたわごとですが。
まつもと ゆきひろ /:|)
> |共有資源が一貫しない状態にあるときにロックが解除されても、それはそれで
> |困るんですよね。やっぱり殺すのって難しい。
>
> 同意します。やはり殺すことにはそれなりにリスクが伴うのでは。
>
> 「まずい*かもしれない*から殺さない」というのは現実世界では当
> 然の戦略ですが、「まずくないようにしてから殺す(まずいことが
> 起きたら自己責任)」というのが、ソフトウェア的なやり方なのか
> なあ。単なるたわごとですが。
万能の解決策はなさそうですよね。
Ruby -- 殺す人が責任を持つ。
Java (deprecatedなThread#killを使う)
-- 殺す人が責任を持つ。
Java (Thread#killを使わない)
-- 殺せない。なんとかして「死んでくれ」とスレッドに伝えて自殺
してもらう。
pthread
-- cancelされたスレッドの状態によって、
・cancel要求を無視する
・即座にcancelされる
・次のcancellation pointに達したときにcancelされる
のいずれかになる。
「死ね」と言われたときに後始末(共有資源を一貫した状態にロールバック)
してから死ぬようにすれば良いんでしょうけど、いつでもできるとは限らない
し、言語やライブラリで保証するのは無理ですね。
たとえばRubyで
mutex.synchronize do
排他処理
ensure
後始末
end
とか書けると多少便利なのかな...
後始末で無限ループとかデッドロックとかされると困っちゃうけど。
前田敦司
MAEDA Atusi <ma...@cc.tsukuba.ac.jp> writes:
|> 「まずい*かもしれない*から殺さない」というのは現実世界では当
|> 然の戦略ですが、「まずくないようにしてから殺す(まずいことが
|> 起きたら自己責任)」というのが、ソフトウェア的なやり方なのか
|> なあ。単なるたわごとですが。
|
|万能の解決策はなさそうですよね。
ですねえ。
|たとえばRubyで
|mutex.synchronize do
| 排他処理
|ensure
| 後始末
|end
|とか書けると多少便利なのかな...
mutex.synchronize do
begin
排他処理
ensure
後始末
end
end
なら現状でも書けます。ってのが答えかどうか分からないんですが。
|後始末で無限ループとかデッドロックとかされると困っちゃうけど。
それはそうですねえ。
> mutex.synchronize do
> begin
> 排他処理
> ensure
> 後始末
> end
> end
>
> なら現状でも書けます。ってのが答えかどうか分からないんですが。
ふむ。そしてスレッドが殺されるときに、後始末が実行されるんですか...
mutex.synchronizeとはまた別に、スレッドが死ぬときにはスタックを巻き戻
して(その道々、ensureを実行しつつ)全部きれいにしてから死ぬのかな?
前田敦司