
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 $
問題なくシグナルを捕捉し、終了したことが確認できました。