使用Python安装信号处理程序

1 投票
2 回答
8643 浏览
提问于 2025-04-16 16:37

(这个问题有后续讨论,可以在这里查看)

我正在尝试为Linux编写一个基于Python的初始化系统,但在将信号发送到我的Python初始化脚本时遇到了问题。从'man 2 kill'页面上可以了解到:

The only signals that can be sent to process ID 1, the init process,  are  those for which init has explicitly installed signal handlers.

在我的Python初始化中,我设置了一个测试函数和一个信号处理器来调用这个函数:

def SigTest(SIG, FRM):
    print "Caught SIGHUP!"

signal.signal(signal.SIGHUP, SigTest)

从另一个TTY(我的初始化脚本在另一个tty上执行sh)发送信号时,它完全被忽略,文本从未打印出来。比如我用命令kill -HUP 1

我发现这个问题是因为我为我的Python初始化编写了一个回收函数,用来处理它的子进程在死亡时的情况,但这些子进程都变成了僵尸进程,花了我一段时间才搞明白Python从未收到SIGCHLD信号。为了确保我的环境正常,我写了一个C程序来创建一个子进程,并让子进程向PID 1发送信号,结果是信号成功注册了。

如果signal.signal(SIG, FUNC)不起作用,我该如何安装一个系统会认可的信号处理器呢?

我打算尝试使用ctypes来用C代码注册我的处理器,看看是否有效,但如果可能的话,我更希望得到一个纯Python的解决方案。

有什么想法吗?

(我不是程序员,真的有点不知所措 :p )

下面是测试代码...

import os
import sys
import time
import signal


def SigTest(SIG, FRM):
    print "SIGINT Caught"

print "forking for ash"
cpid = os.fork()
if cpid == 0:
    os.closerange(0, 4)
    sys.stdin = open('/dev/tty2', 'r')
    sys.stdout = open('/dev/tty2', 'w')
    sys.stderr = open('/dev/tty2', 'w')
    os.execv('/bin/ash', ('ash',))

print "ash started on tty2"

signal.signal(signal.SIGHUP, SigTest)

while True:
    time.sleep(5.0)

2 个回答

0
import signal

from signal import api_client

# Create an instance of the Signal API client

sig = api_client('YOUR_API_KEY')

# Send a message using the Signal API

sig.send_message(recipient='TOKEN', message='Hello world!')

当然可以!请把你想要翻译的内容发给我,我会帮你把它变得更简单易懂。

1

信号处理器在Python中大多数情况下是可以工作的,但也有一些问题。一个问题是,信号处理器不会立即运行,直到解释器重新进入它的字节码解释器。如果你的程序在一个C语言的函数中被阻塞,那么信号处理器就不会被调用,直到这个函数返回。你没有展示你在等待的代码。你是不是在用signal.pause()?

另一个问题是,如果你正在进行系统调用,那么在信号处理器返回后,你会遇到一个异常。你需要把所有的系统调用都包裹在一个重试处理器里(至少在Linux上是这样)。

有趣的是,你在写一个init替代品……这有点像一个进程管理器。proctools的代码可能会引起你的兴趣,因为它确实处理SIGCHLD信号。

顺便说一下,这段代码:

import signal

def SigTest(SIG, FRM):
    print "SIGINT Caught"

signal.signal(signal.SIGHUP, SigTest)

while True:
    signal.pause()

在我的系统上是可以工作的。

撰写回答