我正在使用 Python 3.7 和 subprocess
库。
我有一个二进制 my_prog
,它因段错误而崩溃:
$> ./my_prog
[1] 9328 segmentation fault ./my_prog
在我的脚本 main.py
中,我有这些代码行:
try:
output = subprocess.check_output(['./my_prog'], shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exc:
print(exc.returncode)
print(exc.output)
在这种情况下,我得到
$> python3 main.py
-11
b''
好的,子进程捕获信号 SIGSEGV。
好的,没有输出。为什么不。
但是,如果我想让同一个程序在 stdin 上读取,我必须修改 main.py
中的行(文件“text.txt”存在):
output = subprocess.check_output(['./my_prog < text.txt'], shell=True, stderr=subprocess.STDOUT)
在这种情况下,我得到:
$> python3 main.py
139
b'/bin/sh: line 1: 17235 Segmentation fault: 11 ./my_prog < text.txt\n'
我知道它是 11 + 128,这也意味着 SIGSEGV。
而且,现在,我有一个输出!
即使 139 和 -11 表示相同,为什么返回码在这两种不同情况下会发生变化?为什么第一种情况没有输出?
谢谢:)
编辑:
添加输出问题的差异。
最佳答案
为了提高效率,在某些情况下,shell 仅exec
它运行的最后一个(或唯一一个)命令。然后该命令是与 shell 相同的进程——您的 Python 脚本的直接子——并以通常的方式报告信号(完全如 -11)。
重定向输入可以防止这种情况,也许是为了避免过早关闭在终端上打开的所有文件描述符的问题。然后将来自 my_prog
的段错误报告给 shell:作为带有 -11 的 if,但这实际上是 Python 约定。 shell 打印 一条消息(注意 /bin/sh
出现在其中)和 converts that report进入退出状态 139。
它可以重新呈现信号,在它不exec
的情况下,通过用相同的信号杀死自己(strace
这样做),但它不会为额外的检查而烦恼。 (这样你就不必怀疑 shell 本身是否崩溃了。)不幸的是,shell 以这种方式进一步限制了可用退出状态的范围,但它早已确立。
关于Python 子进程 : in which case a segfault program returns -11 or 139?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53100218/