为什么由于分段错误而被杀死的子进程不会立即死亡?
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++ 程序。
我需要编写接受特定输入并打印相应输出的 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++ 程序。