53157


Python のスクリプトを書いています。

最初は signal を受信したらハンドラ内でファイル I/O 処理など様々な処理を書いていました。スクリプトを実行し、`kill -TERM <PID>`
を実行するとシグナルハンドラ `handler()` が呼ばれ、様々な処理をするコードです。

[code]

    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)
    
[/code]

が、ふと、signal ハンドラ内で重い処理をおこなっていいのか疑問に思い、ググったり、いろいろ調べたところ
[Linuxプログラミングインタフェース](https://www.oreilly.co.jp/books/9784873115856/)「21章
シグナルハンドラの設計」に以下のように書いてありました。

>
> 「すべてのシステムコール、ライブラリ関数が、シグナルハンドラ内で安全に実行できる訳ではありません。その理由を理解するには、リエントラントな関数、および非同期シグナルセーフな関数という
> 2 つの概念が必要になります。(p.444)

ここで、「非同期シグナルセーフ」はいわゆるスレッドセーフのことのようです。

つまり、ファイル I/O
等の処理はたとえばマルチスレッドとして実装し、シグナルハンドラからはスレッドを起こすだけ、といったようにしないといけない。と理解したのですが、このような理解であっているでしょうか？

たとえばこのような実装をイメージしています:

[code]

    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)
    
[/code]


CC BY-SA 4.0
2019-03-01T16:58:05.507
53120
2019-03-03T06:01:31.813
9592
question
python マルチスレッド
Python でのシグナルハンドラ内の処理


> >
> 「すべてのシステムコール、ライブラリ関数が、シグナルハンドラ内で安全に実行できる訳ではありません。その理由を理解するには、リエントラントな関数、および非同期シグナルセーフな関数という
> 2 つの概念が必要になります。(p.444)

システムによって「非同期シグナルセーフな関数(システムコール)」は具体的に定められており、シグナルハンドラ中ではこれ以外の関数(システムコール)を呼んではいけないことになっています。スレッドセーフとは異なります。

<https://docs.oracle.com/cd/E19683-01/816-3976/gen-24356/index.html>  
<https://www.jpcert.or.jp/sc-rules/c-sig30-c.html>

シグナルハンドラにおけるリエントラントとは、シグナルハンドラの処理中に再度割り込みが発生しても安全であることを意味します。(広義の「非同期シグナルセーフ」)

> [Python のシグナルハンドラは、低水準 (C言語)
> のシグナルハンドラ内で実行されるわけではありません。](https://docs.python.org/ja/3.8/library/signal.html)

ということなので、Pythonのレベルでは「非同期シグナルセーフ」がどのように要求されているかはまた異なります。


CC BY-SA 4.0
2019-03-03T06:01:31.813
53157
2019-03-03T06:01:31.813
5793
53120
answer