マルチスレッドの Python プログラムでは、1 つのスレッドが組み込みのraw_input()を使用してコンソール入力を要求することがあります。raw_input プロンプトが表示されているときに、シェルで ^C と入力して (つまり、SIGINT シグナルを使用して) プログラムを終了できるようにしたいと考えています。ただし、子スレッドが raw_input を実行している場合、^C と入力しても何も起こりません。Return を押す (raw_input を離れる) まで、KeyboardInterrupt は発生しません。
たとえば、次のプログラムでは:
import threading
class T(threading.Thread):
def run(self):
x = raw_input()
print x
if __name__ == '__main__':
t = T()
t.start()
t.join()
^C と入力しても、入力が終了するまで何も起こりません。ただし、呼び出すだけの場合T().run()
(つまり、シングルスレッドの場合: メインスレッドで raw_input を実行するだけ)、^C はすぐにプログラムを閉じます。
おそらく、これは SIGINT がメイン スレッドに送信され、コンソール上でフォークされたスレッド ブロックが読み取られている間、メイン スレッドが中断されている (GIL を待機している) ためです。メイン スレッドは、raw_input が返された後に GIL を取得するまで、シグナル ハンドラを実行できません。(これについて間違っている場合は訂正してください。私は Python のスレッド実装の専門家ではありません。)
SIGINT をメインスレッドで処理できるようにしながら、raw_input のような方法で stdin から読み取り、プロセス全体をダウンさせる方法はありますか?
[Mac OS X といくつかの異なる Linux で上記の動作を確認しました。]
編集:上記の根本的な問題を誤解しています。さらに調査すると、join()
シグナル処理を妨げているのはメイン スレッドの呼び出しです。これは、スレッド全体が終了するまでシグナルが実際に延期されていることを意味します。したがって、これは実際にはまったく関係ありませんraw_input
(結合が完了しないようにバックグラウンド スレッドがブロックされているという事実だけです)。