Engineering Note

プログラミングなどの技術的なメモ

Python シグナルAPIの操作

signal

Pythonでは、signalモジュールによりUnixLinuxで扱われるシグナルに纏わる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
 $

 

問題なくシグナルを捕捉し、終了したことが確認できました。

 

参考書籍

ふつうのLinuxプログラミング 第2版 Linuxの仕組みから学べるgccプログラミングの王道