为什么由于分段错误而被杀死的子进程不会立即死亡?

Why does a child process killed due to a segmentation fault not die immediately?

我需要编写接受特定输入并打印相应输出的 C++ 代码。此代码旨在 运行 使用 Python 子流程模块。无论输入和输出如何,我都需要确保 Python 代码不会由于 C++ 代码遇到 运行 时间错误而过早终止。 C++代码的基本性质如下

int main()
{
  /*The pointer is initialized to NULL to simulate a segmentation fault
    Also the n is meant for simulating input.*/
  int *p=NULL,n;   
  cin>>n;
  cout<<*p<<endl;  //This causes a segmentation fault.
}

运行它的Python代码如下:

from subprocess import *
from signal import *

def handler(signum,frame):
    raise RuntimeError("Runtime Error")

call(["g++","try.cpp"])
a = Popen(["stdbuf","-i0","-o0","-e0","./a.out"],stdin = PIPE,stdout = PIPE)
try:
    #Handler for signal due to termination of child process
    signal(SIGCHLD,handler)    
    a.stdin.write("1\n")
    temp = a.stdout.readline()
except RuntimeError as e:
    print e
    print a.returncode   

#Returncode of process killed due to SIGSEGV is -11
    if a.returncode == -11:   
        print "Segmentation Fault Occurred"

这就是问题所在。即使 C++ 代码遇到段错误,调用信号处理程序,引发 RuntimeError,但 Popen 对象的返回码是 none,表明进程仍然存在。
现在,如果对 except 块进行以下更改:

a.wait()
print a.returncode        
if a.returncode == -11:   
    print "Segmentation Fault Occurred"

问题已解决。输出显示 Popen 对象的返回码是 -11 并且 "Segmentation Fault Occurred" 被打印到屏幕上。
如果我尝试模拟因被零除而导致的浮点异常,则会发生完全相同的情况。
为什么会这样?

来自文档

Popen.wait() Wait for child process to terminate. Set and return returncode attribute.

所以 returncode 直到调用 wait 才被设置。

或者您可以执行非阻塞检查以查看进程是否使用 poll 终止,如果终止也会设置 returncode

Popen.poll() Check if child process has terminated. Set and return returncode attribute.

请注意,您实际上并不需要 signal 调用(不确定它是否可以在 Windows 上移植)。代码可以这样简化:

a = Popen(["stdbuf","-i0","-o0","-e0","./a.out"],stdin = PIPE,stdout = PIPE)
a.stdin.write("1\n")
a.stdin.flush()
temp = a.stdout.readline()
if temp:
    # do something
    print("output "+temp)
else:
    # empty string: recieved process has ended, probably unexpectedly
    # because it should have printed something
    pass

returncode = a.wait()

#Returncode of process killed due to SIGSEGV is -11
if returncode  == -11:   
    print("Segmentation Fault Occurred")

请注意,您必须 a.stdin.flush() 以确保输入到达 c++ 程序。