Skip to content

Instantly share code, notes, and snippets.

@fortune
Last active February 3, 2023 12:20
Show Gist options
  • Save fortune/acfa75ca4095b858894574e4b505079a to your computer and use it in GitHub Desktop.
Save fortune/acfa75ca4095b858894574e4b505079a to your computer and use it in GitHub Desktop.
Python プロセスのシグナル制御のサンプルコード

Python プロセスのシグナル制御のサンプル

"""
Process をシグナルで制御するサンプルコード
Python でシグナルハンドラを設定しても、低水準 (C言語) のシグナルハンドラ内で実行されるわけではない。
低水準のシグナルハンドラがフラグを立て、Python コードを実行する VM が 後で、対応するシグナルハンドラを実行できるようにする。
シグナルが受信されたとき、時間のかかる C 拡張を実行していたりすると、そのシグナルに設定しておいたシグナルハンドラが
実行されるまで時間がかかることがある。VM がフラグを見るのは、C 拡張が終わった後だろうから。とはいえ、デフォルト動作であるなら
そのようなことはない。たとえば、SIGTERM に対するデフォルト動作はプロセス終了なので、Python でそれにシグナルハンドラを
設定していなければ、SIGTERM 発生時に C 拡張を実行していたとしても直ちに終了する。
SIGINT については、Python の KeyboardInterrupt 例外をスローするシグナルハンドラが設定されている。これが望む動作でないなら上書きすればいい。
"""
from multiprocessing import Process
import signal
import time
def handler(signo, _):
"""
シグナルハンドラ
signo -- ハンドラを起動したシグナルの番号
_ -- スタックフレーム(ここでは使用しない)
"""
signal.signal(signo, signal.SIG_DFL)
print('Catche ' + str(signo))
def worker(signo):
"""
サブプロセス本体となる関数
signo -- 対象とするシグナル番号
"""
signal.signal(signo, handler) # ハンドラを設定
#signal.signal(signo, signal.SIG_IGN) # シグナルを無視
#signal.signal(signo, signal.SIG_DFL) # デフォルト動作
i = 0
while True:
print(i)
i += 1
time.sleep(1)
p = Process(target=worker, args=(signal.SIGTERM,), daemon=True)
p.start()
p.terminate() # "Catch 15" と出力
p.terminate() # 終了する
p.exitcode # SIGTERM のシグナル番号は 15 なので、-15 になる。
# プロセスが終了したとき、それはゾンビプロセスになる。p.exitcode または p.join() または p.is_alive() を実行すると、
# ゾンビ状態が解消される。また、別の新たなプロセスを開始しても解消される。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment