Определение ошибки сегментации подпроцесса python

Я пишу программу, которая оценивает студенческие программы, и, как я уверен, вы можете себе представить, они иногда имеют недостатки сегментации. Проблема, с которой я сталкиваюсь, заключается в том, что когда ошибка сегментации студенческих программ отсутствует, нет никаких указаний на то, что произошло.

    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, и с этой целью видел несколько сообщений, включая this, которые касаются сбора результатов, но мне все равно, о выходе, хотя было бы неплохо получить строку "Сегментационная ошибка" из stderr, но мне действительно нужен способ окончательно рассказать, что произошло с подпроцессом.

Ответ 1

Ну, на самом деле, в 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

В первом случае процесс "segfaults" (убив себя SIGSEGV), и поэтому wait возвращает -11. В последнем случае процесс завершается с кодом возврата -11, а итоговое значение wait равно 245 (256-11). Поэтому вы можете быть уверены, что любое отрицательное возвращаемое значение из wait должно представлять фатальный сигнал, а не нормальный возврат. Обратите внимание, однако, что процессы могут убить себя, чтобы подделать фатальную ошибку.