确定python子进程分段是否出错

确定python子进程分段是否出错,python,segmentation-fault,subprocess,Python,Segmentation Fault,Subprocess,我正在写一个给学生课程打分的程序,我相信你们可以想象,它们有时会出错。我遇到的问题是,当学生程序分段出现故障时,没有迹象表明发生了什么 proc = subprocess.Popen(student_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.stdout, self.stderr = proc.communicate

我正在写一个给学生课程打分的程序,我相信你们可以想象,它们有时会出错。我遇到的问题是,当学生程序分段出现故障时,没有迹象表明发生了什么

proc = subprocess.Popen(student_command, 
                        stdout=subprocess.PIPE, 
                        stderr=subprocess.PIPE)
self.stdout, self.stderr = proc.communicate()
self.returncode = proc.returncode
我从
子进程中提取
stderr
stdout
,以及返回代码,但是如果程序分段出错,
stderr
为空,
stdout
为空,返回代码为-11。现在,我可以寻找-11退出代码,并假设如果这是返回代码,则存在分段错误,但也没有什么可以阻止学生的代码将-11作为返回代码,仅仅因为学生想要返回-11


如何判断子流程分段是否出错,而不是仅仅感觉返回-11?我真的不太关心stderr和stdout中的内容,为此,我看过很多帖子,包括关于获取输出的文章,但我不太关心输出,尽管从stderr中提取“分段错误”字符串会很好,但是我真正需要的是一种方法来明确地告诉子进程发生了什么。

事实上,在UNIX上,试图返回
-11
的进程通常会返回一个正整数。这是因为
wait
系列函数的返回状态实际上是一组位字段,其中一个字段用于结束处理的信号,另一个字段用于返回值。Python解码这些位字段的
wait
返回值

在大多数系统上,这些字段是无符号的,大小为8位,因此您可能会看到类似的情况:

>>> import subprocess
>>> subprocess.Popen(['python','-c','import os; os.kill(os.getpid(),11)']).wait()
-11
>>> subprocess.Popen(['python','-c','exit(-11)']).wait()
245

在前一种情况下,进程“segfults”(通过SIGSEGV自杀),因此
wait
返回-11。在后一种情况下,进程退出时返回代码为-11,得到的
wait
值为245(256-11)。因此,您可以放心,来自
wait
的任何负返回值都必须表示致命信号,而不是正常返回。不过,请注意,进程可能会为了伪造致命错误而自杀。

请注意,学生代码也可能以其他奇妙的方式消亡,如
SIGABRT
(通过破坏堆等方式触发断言)、
SIGBUS
(某些平台上的访问未对齐),
SIGXCPU
(假设你有合适的限制器,CPU时间就用完了),
SIGFPU
(除以零)和其他各种可怕的方式。做好滥用的准备。另外,不要硬编码“-11”,您应该在
信号
模块中使用符号常量。因此,可以通过检查返回值的符号来区分刚返回-11的程序和因segfault而死亡的进程?为什么后者不返回-11?在大多数UNIXy系统上,包括Linux,返回代码是无符号的,为8位在大小上,so-11被转换为245(无符号8位双补表示-11)。