JVM thread interruption

3
Sadayuki Furuhashi @frsyuki

厳密には、readで待っている最中、またはスレッドのinterruptフラグがセットされた状態で呼ばれたときに、チャネルをclose()し、さらにスレッドのinterruptフラグをセットし直し、それからClosedByInterruptExceptionを投げる。

2014-08-05 04:07:27
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@frsyuki それちゃんと動いてるのかな。LinuxはOSレベルではIO中に別のスレッドからcloseされた場合の動作は保証してないけど。まあ、ソース読めばいいんだけど

2014-08-05 04:07:33
Sadayuki Furuhashi @frsyuki

と、ドキュメントに書いてある。

2014-08-05 04:07:38
Sadayuki Furuhashi @frsyuki

@kosaki55tea FileChannel.readはFileDispatcherImpl.read0に行き着くようですが、それ自体はerrno == EINTRだったら例外を投げるだけな感じがしますね。

2014-08-05 04:11:59
Sadayuki Furuhashi @frsyuki

何やらJava側で実装してある感じかな。 “AbstractInterruptibleChannel” docs.oracle.com/javase/7/docs/…

2014-08-05 04:13:15
Sadayuki Furuhashi @frsyuki

sun.misc.SharedSecrets.getJavaLangAccess().blockedOnという謎メソッドに行き着く。

2014-08-05 04:15:07
Sadayuki Furuhashi @frsyuki

結局、サーバの終了方法はどうするかな。FileInputStream.readを中断できない(たぶんSocketInputStreamも?)以上は、動作中のサーバプロセスを安全に即座に止めるのは厳しいというかイケてない感じなので、処理が終わるまで待つのが基本かな。

2014-08-05 04:20:03
Sadayuki Furuhashi @frsyuki

しかしスレッドが1本でも忙しくしていると、サーバを長時間再起動できない可能性があるというのも困るので、忙しいスレッドは処理中のまま放置しておいて新しいプロセスを立ち上げられるようにするか、忙しいスレッドをゴミの発生覚悟でひと思いにブチ殺す仕組みがあると良い。

2014-08-05 04:22:07
Sadayuki Furuhashi @frsyuki

もしくは、finallyをちゃんと呼ばせつつ、best effortで止めるか。

2014-08-05 04:24:54
Sadayuki Furuhashi @frsyuki

1.shutdown handlerでshutdown的なメソッドを呼んで全スレッドの終了を静かに待つ。2.時間がかかりすぎたら、Thread.interruptを呼んで回って積極的に止めようとしてみる。3.それでも時間がかかりすぎたら、多少の遺言を残して自決する。こんな感じか。

2014-08-05 04:27:59
Sadayuki Furuhashi @frsyuki

2.の代わりに、supervisor的なプロセス側で、既存JVMプロセスの終了を待たずに新プロセスを立ち上げてしまう仕組みを入れる方法もある。どちらかだな。

2014-08-05 04:30:30
Sadayuki Furuhashi @frsyuki

後者の方法+ServerEngineでsupervisor的なプロセスを作るのが一番シンプルそうだけど、真面目に検証するのは大変そうだから後回しにする案。とりあえず運用でカバーだ。

2014-08-05 05:00:28
Sadayuki Furuhashi @frsyuki

そういえば、結局InterruptedIOExceptionが何なのか良く分からないな。発生する条件が不明というか使い所が不明。ClosedByInterruptExceptionは分かったけど。

2014-08-05 05:25:20