Python でのシグナルハンドラ内の処理
Python のスクリプトを書いています。
最初は signal を受信したらハンドラ内でファイル I/O 処理など様々な処理を書いていました。スクリプトを実行し、kill -TERM <PID>
を実行するとシグナルハンドラ handler()
が呼ばれ、様々な処理をするコードです。
import signal
import time
import os
def handler(num, frame):
print("handler")
# do something
signal.signal(signal.SIGTERM, handler)
print("sleep... {0}".format(os.getpid()))
time.sleep(60)
が、ふと、signal ハンドラ内で重い処理をおこなっていいのか疑問に思い、ググったり、いろいろ調べたところ Linuxプログラミングインタフェース「21章 シグナルハンドラの設計」に以下のように書いてありました。
「すべてのシステムコール、ライブラリ関数が、シグナルハンドラ内で安全に実行できる訳ではありません。その理由を理解するには、リエントラントな関数、および非同期シグナルセーフな関数という 2 つの概念が必要になります。(p.444)
ここで、「非同期シグナルセーフ」はいわゆるスレッドセーフのことのようです。
つまり、ファイル I/O 等の処理はたとえばマルチスレッドとして実装し、シグナルハンドラからはスレッドを起こすだけ、といったようにしないといけない。と理解したのですが、このような理解であっているでしょうか?
たとえばこのような実装をイメージしています:
import signal
import threading
import time
import os
event = threading.Event()
def funcA():
print("start funcA")
event.wait()
print("end funcA")
def handler(num, frame):
print("handler")
event.set()
signal.signal(signal.SIGTERM, handler)
th = threading.Thread(target = funcA)
th.start()
print("sleep... {0}".format(os.getpid()))
time.sleep(60)