如何使用subprocess和preexec_fn处理子进程的SIGFPE/SIGILL信号?

3 投票
2 回答
1311 浏览
提问于 2025-04-17 13:24

在Linux系统上,我有一个可执行文件,我想通过Python脚本来运行它。这个可执行文件在运行时会出现除以零的错误,而我似乎无法处理子进程发出的信号。我查了一些资料,发现preexec_fn应该能处理SIGFPE信号,但到现在为止都没有成功。

我使用的是Python 2.7。

我的代码是:

# b.py
import os
import subprocess
import signal
import sys

def pref_fun():
    signal.signal(signal.SIGFPE,foo)

def foo(signal,frame):
    print "Caught signal!"
    sys.exit(0)

sub = subprocess.Popen(["a.out"], preexec_fn=pref_fun)
sub.wait()
v = sub.returncode
print "value: ", v

还有我的子进程:

a.c
#include <stdio.h>
#include <stdlib.h>
int main() {
    printf("Now dividing by zero\n");
    fflush(stdout);
    double x = 5;
    x= 5/0;
    printf("oh no\n");
    return 0;

}

我期待的输出是“捕获到信号!”,但我似乎没有得到这个结果。

2 个回答

0

确保你的Python是用这个配置选项编译的:
--with-fpectl 启用SIGFPE捕获

1

我担心我们不能这样做。虽然在子进程中安装了信号处理器,但当执行了 ./a.out 并用 exec() 替换时,原本有信号处理器的程序被新的程序替换了——所以子进程中就没有信号处理器了。不过,我们可以通过 os.WIFSIGNALED(v) 来检查子进程是否是因为信号而终止的,如果返回值是 True,我们可以用 os.WTERMSIG(v) 来获取具体是哪个信号导致的,之后我们可以在父进程中做一些处理。

不过,我在我的机器上使用 os.WTERMSIG(v) 得到了很奇怪的结果,发现实际的信号编号似乎是 v 的负数(我检查过 SIGSEGVSIGFPE),我不知道这是不是我机器的问题,反正希望这对你有帮助 :)。

import os
import subprocess
import signal
import sys 

def pref_fun():
    signal.signal(signal.SIGFPE,foo)

def foo(signal,frame):
    print "Caught signal!"
    sys.exit(0)

sub = subprocess.Popen(["./a.out"], preexec_fn=pref_fun)
sub.wait()
v = sub.returncode
print "value: ", v
print os.WIFSIGNALED(v)
print "signal:", os.WTERMSIG(v)
print "SIGFPE", signal.SIGFPE    

输出结果是:

Now dividing by zero
value:  -8
True
signal: 120
SIGFPE 8

撰写回答