【问题标题】:Installing signal handler with Python使用 Python 安装信号处理程序
【发布时间】:2011-08-15 04:06:50
【问题描述】:

(这个问题有后续here

我正在尝试为 Linux 编写基于 Python 的 Init 系统,但在获取 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 的 Init 中,我有一个测试函数和一个信号处理程序设置来调用该函数:

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

signal.signal(signal.SIGHUP, SigTest)

如果我从另一个 TTY(初始化脚本在另一个 tty 上执行 sh)发送一个信号,它会被完全忽略,并且永远不会打印文本。 kill -HUP 1

我发现这个问题是因为我为我的 Python init 编写了一个 reaping 函数,以便在其子进程死亡时获取它们,但它们都只是僵死了,花了一段时间才发现 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)

【问题讨论】:

    标签: python c linux init signal-handling


    【解决方案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()
    

    在我的系统上工作。

    【讨论】:

    • 我没有使用signal.pause(),我试试看。我用我正在使用的测试代码编辑了帖子
    • 啊哈,sleep() 函数会阻塞你的信号处理程序,直到它完成。这就是为什么我必须编写一个alternative sleep 模块。它在中断时调用 C API PyErr_CheckSignals。这使得信号处理程序能够被调用。
    • 将 sleep() 更改为 signal.pause() 也不起作用。我还尝试将 sleep() 更改为 0.01(以使其看起来更加即时),但信号仍然没有被捕获。内核?必须阻止所有信号...... C prog 和 Python prog 安装信号处理程序的方式必须有所不同。
    • 处理它们的方式有所不同。正如我所说,我确实在 Python 中使用了信号,但我所做的更改。
    • 对已编译的 C 程序和 python 脚本进行 strace 设置信号处理程序,看起来它们都使用系统调用“rt_sigaction”。然而,看起来python程序试图为同一个信号设置2x——第一次为null而不是稍后使用该函数? rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0rt_sigaction(SIGINT, {0x4d7270, [], SA_RESTORER, 0x7f928fce0b40}, {SIG_DFL, [], 0}, 8) = 0。也许它只注册第一个?
    猜你喜欢
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多