Python シグナルAPIの操作
Pythonでは、signalモジュールによりUnixやLinuxで扱われるシグナルに纏わるAPIを利用することができます。
今回はsignalの基本的な使い方について学んでいきます。
signalとは
signalは、ユーザやカーネルがプロセスに対して通知を送信する仕組みで、実際はint型の整数となります。
signal.h
でその番号の一覧を確認することができ、以下は特に重要なものを抜粋しました。
... #define SIGHUP 1 /* ハングアップシグナルで、デーモンのリセットなどに使用する */ #define SIGINT 2 /* 割り込みシグナルで、キーボードから「CTRL+C」で中断させる */ #define SIGQUIT 3 /* クイットシグナルで、キーボードから「CTRL+\」で中止させる */ #define SIGKILL 9 /* キルシグナルで、プロセスを強制終了させる */ #define SIGTERM 15 /* 終了シグナルで、プロセスを終了させる */ ...
各シグナルでは、デフォルトでその挙動が決められていますが、シグナルAPIを利用することで、その挙動を変えることが可能になります。
今回はSIGINTを捕捉(catchやtrapと呼ぶ)するスクリプトを作成してみます。
なお、Pythonでは以下のsignalモジュールのsignalメソッドを利用します。
signal.signal(signalnum, handler)
handlerでは二つの引数をとるハンドラ関数か、SIG_IGN(Ignore)およびSIG_DFL(Default)の特殊な値を使います。
スクリプトの作成
それでは上記APIを利用したプログラムを作成します。
スレッドでシグナル待ちのメッセージを出力し、SIGINTを捕捉したらその旨を出力し終了します。
# signal.py import signal import time from threading import Thread FLAG = False def handler(signum, frame): global FLAG print("signal={}".format(signum)) FLAG = True def waiting(): global FLAG while not FLAG: print("Waiting for signal...") time.sleep(2) t = Thread(target=waiting, args=[]) t.start() signal.signal(signal.SIGINT, handler) signal.pause()
動作確認
それでは、上記で作成したスクリプトを実行してみます。
$ python3 signal.py Waiting for signal... Waiting for signal... Waiting for signal... ^Csignal=2 $
問題なくシグナルを捕捉し、終了したことが確認できました。