获取用python将SIGTERM发送到当前进程的进程的PID

获取用python将SIGTERM发送到当前进程的进程的PID,python,signals,ctypes,Python,Signals,Ctypes,我有一个脚本正在做一些事情,例如自动测试。由于未知的原因,它被一个SIGTERM信号随机终止——目标是试图识别谁在发送信号——发送者的PID 我尝试过使用信号库,但是它似乎没有提供足够的关于发送方的信息,如果使用像signal.signal(signal.SIGTERM,some_handler)这样的处理程序设置-处理程序只传递信号号(本例中为15)和当前堆栈,这是没有帮助的 我还尝试使用ctypes并创建一个处理程序(基于对的回答),在一些更改之后,我设法让处理程序接受siginfo\u t

我有一个脚本正在做一些事情,例如自动测试。由于未知的原因,它被一个SIGTERM信号随机终止——目标是试图识别谁在发送信号——发送者的PID

我尝试过使用
信号
库,但是它似乎没有提供足够的关于发送方的信息,如果使用像
signal.signal(signal.SIGTERM,some_handler)这样的处理程序设置
-处理程序只传递信号号(本例中为15)和当前堆栈,这是没有帮助的

我还尝试使用
ctypes
并创建一个处理程序(基于对的回答),在一些更改之后,我设法让处理程序接受
siginfo\u t
——但是
siginfo\u t.contents.si\u pid
siginfo\u.contents.si\u code
的值对我来说没有意义,因为它们与发送者的pid不相似,代码不是15

我使用的代码如下所示:

#!/usr/bin/env python3

import sys
import os
import time
from ctypes import Structure, Union, POINTER, CFUNCTYPE, CDLL, byref, sizeof, \
    c_short, c_int, c_uint, c_long, c_ulong, c_char_p, c_void_p


SIGTERM = 15
SA_SIGINFO = 4

class sigset_t(Structure):
    _fields_ = [
        ("__val", c_ulong * (1024 // (8 * sizeof (c_long)))),
    ]


class sigval_t(Union):
    _fields_ = [
        ("sival_int", c_int),
        ("sival_ptr", c_void_p),
    ]


class siginfo_t(Structure):
    _fields_ = [
        ("si_signo", c_int),
        ("si_errno", c_int),
        ("si_code", c_int),
        ("_pad", c_int * 29),
        ("si_pid", c_uint)
    ]


sa_sigaction_functype = CFUNCTYPE(None, c_int, POINTER(siginfo_t), c_void_p)

sa_handler_functype = CFUNCTYPE(None, c_int, use_errno=True)


class SIGACTION(Structure):
    _fields_ = [
        # ("sa_handler", sa_handler_functype),
        ("sa_sigaction", sa_sigaction_functype),
        # ("sa_mask", sigset_t),
        ("sa_mask", siginfo_t),
        ("sa_flags", c_int),
        ("sa_restorer", c_void_p),
    ]


libc = CDLL(None)

def sighandler(sig, siginfo_t, something):  # Signal handler function
    libc.puts.argtypes = [c_char_p]
    libc.puts.restype = c_int
    libc.puts("Custom signal handler called for signal {0:d}".format(sig).encode())
    # print(str(siginfo_t.contents))
    print("Sender PID: " + str(siginfo_t.contents.si_pid))
    print("Signal Number: " + str(siginfo_t.contents.si_signo))


def main(*argv):

    libc.sigaction.argtypes = [c_int, POINTER(SIGACTION), POINTER(SIGACTION)]
    libc.sigaction.restype = c_int

    signal_number = SIGTERM
    act = SIGACTION(
                    # sa_handler=sa_handler_functype(sighandler),
                    sa_sigaction=sa_sigaction_functype(sighandler),
                    sa_flag=SA_SIGINFO)

    res = libc.sigaction(signal_number, byref(act), None)
    print("sigaction result: {0:d}".format(res))
    print("PId {0:d} waiting for SIG {1:d}...".format(os.getpid(), signal_number))

    while 1:
        time.sleep(0.1)


if __name__ == "__main__":
    main(*sys.argv[1:])
    print("\nDone.")
以及调用处理程序时得到的值(信号由PID 14783的进程发送):

siginfo\u t.contents

这是我第一次使用
ctypes
和C(因此,代码可能没有太多意义),因此如果能帮助我澄清为什么会得到无效值以及如何修复它,我们将不胜感激,谢谢


例如,在Ubuntu 18.04.5 LTS上测试的Python 3.8,您的结构不符合
si_pid
在该手册页上位于字节偏移量16(假设为32位int),但您的位于偏移量128。
si_code: 11340640
si_errno: 1
si_pid: 2
si_signo: 1