handle_interrupt(hash) { ... } -> object
[permalink][rdoc]スレッドの割り込みのタイミングを引数で指定した内容に変更してブロックを実行します。
「割り込み」とは、非同期イベントや Thread#raise や Thread#kill、Signal.#trap(未サポート)、メインスレッドの終了 (メインスレッドが終了すると、他のスレッドも終了されます)を意味します。
すぐに割り込みます。
ブロッキング処理(後述)の間は割り込みが発生します。
まったく割り込みません。
「ブロッキング処理」とは、読み込み処理や書き込み処理のような呼び出し元のスレッドをブロックするような処理を意味します。CRuby の実装では、GVL を解放して実行する処理は全てブロッキング処理に含まれます。
また、マスクされた非同期割り込みは再度有効にされるまで延期されます。本メソッドは sigprocmask(3) に似ています。
非同期割り込みの利用は難しいため、スレッド間での通信を実現する場合はまずはキューのような他の方法を検討してください。それでも非同期割り込みを利用する場合は本メソッドをよく理解してから利用してください。
例:Thread#raise 発生のタイミングを制御する例
th = Thread.new do Thead.handle_interrupt(RuntimeError => :never) { begin # 安全にリソースの割り当てが可能 Thread.handle_interrupt(RuntimeError => :immediate) { # ... } ensure # 安全にリソースの解放が可能 end } end Thread.pass # ... th.raise "stop"
RuntimeError を無視(延期)している間はリソースの割り当てや ensure 節でリソースの解放を安全に行う事ができます。
例:TimeoutError 発生のタイミングを制御する例
require 'timeout' Thread.handle_interrupt(TimeoutError => :never) { timeout(10){ # TimeoutError => :never の指定により、ここでは TimeoutError が発生しない。 Thread.handle_interrupt(TimeoutError => :on_blocking) { # :on_blocking な処理は TimeoutError が発生し得る。 } # TimeoutError => :never の指定により、ここでは TimeoutError が発生しない。 } }
この例を ensure 節での TimeoutError 発生に応用する事でリソースリークに備える事ができます。Timeout.#timeout はスレッドを使って実装されているため、Thread.handle_interrupt による制御が有効です。
It's possible to stack multiple levels of ::handle_interrupt blocks in order to control more than one ExceptionClass and TimingSymbol at a time.
Thread.handle_interrupt(FooError => :never) { Thread.handle_interrupt(BarError => :never) { # FooError and BarError are prohibited. } }
本メソッドでは引数 hash のキーに指定した例外クラスの全てのサブクラスが処理の対象になります。
例:
Thread.handle_interrupt(Exception => :never) { # Exception を継承する全ての例外クラスの例外の発生を延期。 }
[SEE_ALSO] Thread.pending_interrupt?, Thread#pending_interrupt?