是否可以捕获分段错误?
Is it possible to trap a segmentation fault?
我的应用程序依赖于 ghostscript
将一些 pdf 文件转换为文档每一页的一系列图像。这是一个简化版本:
import locale
from ghostscript import Ghostscript as gs
from ghostscript import cleanup
from cv2 import imread, IMREAD_GRAYSCALE as GRAY
from multiprocessing import cpu_count
args = [
"",
"-q", "-r300", "-dNOPAUSE",
"-sDEVICE=pgmraw",
"-sOutputFile=%d.pgm",
"-dNumRenderingThreads=" + str(cpu_count()),
"-f", "_.pdf" #filename will always be "_.pdf"
]
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
def pdftoimarray():
cleanup()
gs(*args)
imarray = []
for filename in os.listdir():
imarray.append(imread(filename, GRAY))
return imarray
(我故意在最后删除了文件系统的清理:这对这个问题来说并不重要)
问题是,我真的不能相信这些文件的来源,其中一些可能有错误。 运行 一些测试,我发现其中一些错误的文件导致 ghostscript 实际上发生了段错误,这反过来又使我的整个应用程序崩溃。
通常,段错误是一个非常严重的事件,我们无法真正从中恢复,所以我怀疑是否真的有可能捕获它。但就我而言,它不应该真的那么严重:假设我的程序仍处于有效状态,我可以将该文档标记为 bad 然后继续。
问题:我能否以某种方式在我的依赖项中捕获此分段错误,并从中恢复?
之前在 Segmentation Fault Catch, but the only answer is wrong (It suggests trapping it with signal.signal
, but the documentation clearly says that catching synchronous signals such as SIGSEGV makes little sense using it. The same documentation points to faulthandler 中有人问过这个问题,但它并不能真正捕获信号:它只是在发生这种情况时提供更好的错误消息。
这留下了这个问题如何独特而不是重复的问题:我的限制有所减少:我根本不打算处理这个问题:我只想忽略它并继续前进。任何关于首先实际避免 ghostscript 中的段错误的观点也将得到很好的接受。
这个问题有点老了,但我想我应该分享这个:我正在看一个关于一个很酷的新内存分配器的视频,关于观众的一个问题,作者解释说他 "Installs a segfault handler",这是我非常感兴趣的。我仍然不知道他到底是怎么做到的,所以这并不能完全回答我的问题,但它给了我一个开始研究的好地方。如果我设法自己解决这个问题,我会 post 在这里回答。
这是视频(link是他回答我说的问题的时候)
https://youtu.be/c1UBJbfR-H0?t=2058
我有一个类似的问题,通过 pythonocc 渲染 cad 文件。
有时在打开文件时,脚本会出现段错误。真的很烦人。您必须手动删除文件并重新启动批处理。
所以基本上这个想法是为任务启动一个额外的进程并检查它是 exitcode:
import multiprocessing as mp
def do_stuff_that_segfaults(param):
call_shitty_library(param)
def main():
p = mp.Process(target=do_stuff_that_segfaults, args=param)
p.start()
p.join()
if p.exitcode == -11: # Segmentation fault
do_stuff_in_case_of_segfault()
我也尝试过其他建议,例如您链接到的 Segmentation Fault Catch,但无济于事。
我真的很想使用 mp.pool()
来使用所有内核,但是 you don't get the exit status from mp.pool().
到目前为止,代码运行良好,我通过 do_stuff_in_case_of_segfault()
将导致段错误的文件移动到另一个文件夹,而没有杀死我的主脚本。
我的应用程序依赖于 ghostscript
将一些 pdf 文件转换为文档每一页的一系列图像。这是一个简化版本:
import locale
from ghostscript import Ghostscript as gs
from ghostscript import cleanup
from cv2 import imread, IMREAD_GRAYSCALE as GRAY
from multiprocessing import cpu_count
args = [
"",
"-q", "-r300", "-dNOPAUSE",
"-sDEVICE=pgmraw",
"-sOutputFile=%d.pgm",
"-dNumRenderingThreads=" + str(cpu_count()),
"-f", "_.pdf" #filename will always be "_.pdf"
]
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
def pdftoimarray():
cleanup()
gs(*args)
imarray = []
for filename in os.listdir():
imarray.append(imread(filename, GRAY))
return imarray
(我故意在最后删除了文件系统的清理:这对这个问题来说并不重要)
问题是,我真的不能相信这些文件的来源,其中一些可能有错误。 运行 一些测试,我发现其中一些错误的文件导致 ghostscript 实际上发生了段错误,这反过来又使我的整个应用程序崩溃。
通常,段错误是一个非常严重的事件,我们无法真正从中恢复,所以我怀疑是否真的有可能捕获它。但就我而言,它不应该真的那么严重:假设我的程序仍处于有效状态,我可以将该文档标记为 bad 然后继续。
问题:我能否以某种方式在我的依赖项中捕获此分段错误,并从中恢复?
之前在 Segmentation Fault Catch, but the only answer is wrong (It suggests trapping it with signal.signal
, but the documentation clearly says that catching synchronous signals such as SIGSEGV makes little sense using it. The same documentation points to faulthandler 中有人问过这个问题,但它并不能真正捕获信号:它只是在发生这种情况时提供更好的错误消息。
这留下了这个问题如何独特而不是重复的问题:我的限制有所减少:我根本不打算处理这个问题:我只想忽略它并继续前进。任何关于首先实际避免 ghostscript 中的段错误的观点也将得到很好的接受。
这个问题有点老了,但我想我应该分享这个:我正在看一个关于一个很酷的新内存分配器的视频,关于观众的一个问题,作者解释说他 "Installs a segfault handler",这是我非常感兴趣的。我仍然不知道他到底是怎么做到的,所以这并不能完全回答我的问题,但它给了我一个开始研究的好地方。如果我设法自己解决这个问题,我会 post 在这里回答。
这是视频(link是他回答我说的问题的时候) https://youtu.be/c1UBJbfR-H0?t=2058
我有一个类似的问题,通过 pythonocc 渲染 cad 文件。 有时在打开文件时,脚本会出现段错误。真的很烦人。您必须手动删除文件并重新启动批处理。
所以基本上这个想法是为任务启动一个额外的进程并检查它是 exitcode:
import multiprocessing as mp
def do_stuff_that_segfaults(param):
call_shitty_library(param)
def main():
p = mp.Process(target=do_stuff_that_segfaults, args=param)
p.start()
p.join()
if p.exitcode == -11: # Segmentation fault
do_stuff_in_case_of_segfault()
我也尝试过其他建议,例如您链接到的 Segmentation Fault Catch,但无济于事。
我真的很想使用 mp.pool()
来使用所有内核,但是 you don't get the exit status from mp.pool().
到目前为止,代码运行良好,我通过 do_stuff_in_case_of_segfault()
将导致段错误的文件移动到另一个文件夹,而没有杀死我的主脚本。