[英]How to catch SegFault in Python as exception?
有时 Python 不仅会抛出异常,还会抛出段错误。
根据我多年使用 Python 的经验,我看到了许多段错误,其中一半在二进制模块(C 库,即.so
/ .pyd
文件)中,一半在 CPython 二进制文件本身中。
当出现段错误时,整个 Python 程序以故障转储(或静默方式)结束。 我的问题是,如果段错误发生在某些代码块或线程中,是否有机会通过except
将其作为常规异常捕获,从而防止整个程序崩溃?
众所周知,您可以使用faulthandler ,例如通过python -q -X faulthandler
。 然后它在段错误时创建以下转储:
>>> import ctypes
>>> ctypes.string_at(0)
Fatal Python error: Segmentation fault
Current thread 0x00007fb899f39700 (most recent call first):
File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at
File "<stdin>", line 1 in <module>
Segmentation fault
但是上面的转储完全完成了程序。 相反,我想将此回溯作为一些标准异常进行捕获。
另一个问题是我是否可以在PyRun_SimpleString() function 的 C API 中捕获 Python 代码的段错误?
最简单的方法是拥有一个启动您的应用程序进程的“父”进程,并检查其退出值。 -11
表示进程接收到信号11
,即SEGFAULTV
( cf )
import subprocess
SEGFAULT_PROCESS_RETURNCODE = -11
segfaulting_code = "import ctypes ; ctypes.string_at(0)" # https://codegolf.stackexchange.com/a/4694/115779
try:
subprocess.run(["python3", "-c", segfaulting_code],
check=True)
except subprocess.CalledProcessError as err:
if err.returncode == SEGFAULT_PROCESS_RETURNCODE:
print("probably segfaulted")
else:
print(f"crashed for other reasons: {err.returncode}")
else:
print("ok")
编辑:这是一个使用faulthandler
故障处理程序的 Python 转储的可重现示例:
# file: parent_handler.py
import subprocess
SEGFAULT_PROCESS_RETURNCODE = -11
try:
subprocess.run(["python3", "-m", "dangerous_child.py"],
check=True)
except subprocess.CalledProcessError as err:
if err.returncode == SEGFAULT_PROCESS_RETURNCODE:
print("probably segfaulted")
else:
print(f"crashed for other reasons: {err.returncode}")
else:
print("ok")
# file: dangerous_child.py
import faulthandler
import time
faulthandler.enable() # by default will dump on sys.stderr, but can also print to a regular file
def cause_segfault(): # https://codegolf.stackexchange.com/a/4694/115779
import ctypes
ctypes.string_at(0)
i = 0
while True:
print("everything is fine ...")
time.sleep(1)
i += 1
if i == 5:
print("going to segfault!")
cause_segfault()
everything is fine ...
everything is fine ...
everything is fine ...
everything is fine ...
everything is fine ...
going to segfault!
Fatal Python error: Segmentation fault
Current thread 0x00007f7a9ab35740 (most recent call first):
File "/usr/lib/python3.8/ctypes/__init__.py", line 514 in string_at
File "/home/stack_overflow/dangerous_child.py", line 9 in cause_segfault
File "/home/stack_overflow/dangerous_child.py", line 19 in <module>
File "<frozen importlib._bootstrap>", line 219 in _call_with_frames_removed
File "<frozen importlib._bootstrap_external>", line 848 in exec_module
File "<frozen importlib._bootstrap>", line 671 in _load_unlocked
File "<frozen importlib._bootstrap>", line 975 in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 991 in _find_and_load
File "/usr/lib/python3.8/runpy.py", line 111 in _get_module_details
File "/usr/lib/python3.8/runpy.py", line 185 in _run_module_as_main
probably segfaulted
(两个进程的输出在我的终端中混合在一起,但您可以根据需要将它们分开)
这样您就可以查明问题是由 Python 代码ctypes.string_at
引起的。
但正如马克在评论中指出的那样,如果程序被杀死是因为它做了坏事,你不应该太相信它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.