Skip to content

Instantly share code, notes, and snippets.

@morisono
Forked from fortune/README.md
Created August 12, 2025 09:40
Show Gist options
  • Save morisono/0ee95a2d006758f3afbf66accd09d7b7 to your computer and use it in GitHub Desktop.
Save morisono/0ee95a2d006758f3afbf66accd09d7b7 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)
if __name__ == "__main__":
p = Process(target=worker, args=(signal.SIGTERM,), daemon=True)
p.start()
time.sleep(1) # 子プロセスとのレースコンディションを避けるため。
p.terminate() # "Catch 15" と出力
time.sleep(3) # 子プロセスをしばらく動かしておくため。
p.terminate() # 終了する(SIGTERM を送る)
p.exitcode # SIGTERM のシグナル番号は 15 なので、-15 になる。
# プロセスが終了したとき、それはゾンビプロセスになる。p.exitcode または p.join() または p.is_alive() を実行すると、
# ゾンビ状態が解消される。また、別の新たなプロセスを開始しても解消される。
@morisono
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment