tMC*_*tMC 9 c python linux signals init
这是我用Python修改信号处理程序的另一篇文章的后续文章.简而言之,Linux阻止所有信号到PID 1(包括SIGKILL),除非Init为特定信号安装了信号处理程序; 如果有人要向PID1发送终止信号,以防止内核恐慌.我一直遇到的问题是signal,Python中的模块似乎没有以系统识别的方式安装信号处理程序.我的Python Init脚本似乎完全忽略了所有信号,因为我认为它们被阻止了.
我好像找到了解决方案; 使用ctypes安装与所述信号处理程序signal()在libc函数(在这种情况下uClibc的).下面是一个基于python的测试init.它在TTY2上打开一个shell,我可以从中向PID1发送信号进行测试.它似乎在KVM中用于测试(我愿意与任何感兴趣的人分享VM)
这是解决这个问题的最佳方法吗?在没有信号模块的情况下安装信号处理器是否有"更好"的方法?(我完全不关心可移植)
这是Python中的错误吗?
#!/usr/bin/python
import os
import sys
import time
from ctypes import *
def SigHUP():
print "Caught SIGHUP"
return 0
def SigCHLD():
print "Caught SIGCHLD"
return 0
SIGFUNC = CFUNCTYPE(c_int)
SigHUPFunc = SIGFUNC(SigHUP)
SigCHLDFunc = SIGFUNC(SigCHLD)
libc = cdll.LoadLibrary('libc.so.0')
libc.signal(1, SigHUPFunc) # 1 = SIGHUP
libc.signal(17, SigCHLDFunc) # 17 = SIGCHLD
print "Mounting Proc: %s" % libc.mount(None, "/proc", "proc", 0, None)
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"
print "sleeping"
while True:
time.sleep(0.01)
Run Code Online (Sandbox Code Playgroud)
我在KVM下进行了一些调试,我发现当标准信号模块安装信号处理程序时,内核正在向pid 1发送信号.然而,当接收到信号时,"某事"导致产生过程的克隆,而不是打印预期的输出.
当我将HUP发送到非工作的init.sig-mod时,这是strace输出:

这导致新进程运行(pid 23),它是init.sig-mod的克隆:

我没有时间深入挖掘原因,但这会进一步缩小范围.可能与Python的信号传递逻辑有关(它注册了一个C钩子,在调用时调用你的字节码函数).ctypes技术绕过了这一点.相关的Python源文件是Python/pythonrun.c和Modules / signalmodule.c,以备您仔细查看.
旧信息 - 我不确定这会解决您的问题,但可能会让您更接近.我比较了安装信号处理程序的不同方式:
signal()直接调用系统调用.调用处理程序时,ctypes调用的signal()系统调用和Upstart的sigaction()
系统调用都会设置SA_RESTART标志.设置此标志表示当进程正在执行时接收到信号或在某些系统调用(读取,写入,等待,nanosleep等)内阻塞时,在信号处理程序完成后,应自动重新启动系统调用.该应用程序将不会意识到这一点.
当Python的信号模块注册一个处理程序时,它会通过调用将SA_RESTART标志置零siginterrupt(signum, 1).这告诉系统"当系统调用被信号中断时,信号处理程序完成将errno设置为EINTR并从系统调用返回".这使得开发人员可以处理此问题并决定是否重新启动系统调用.
您可以通过以下方式注册信号来设置SA_RESTART标志:
import signal
signal.signal(signal.SIGHUP, handler)
signal.siginterrupt(signal.SIGHUP, False)
Run Code Online (Sandbox Code Playgroud)