【问题标题】:Is it possible to trap a segmentation fault?是否可以捕获分段错误?
【发布时间】:2019-04-02 17:58:19
【问题描述】:

我的应用程序依赖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 中已经有人问过这个问题,但唯一的答案是错误的(它建议用signal.signal 捕获它,但documentation 明确表示使用它来捕获诸如 SIGSEGV 之类的同步信号毫无意义。相同的文档指向faulthandler,但它不能真正捕获信号:它只是提供更好的错误消息以防万一。

这就留下了这个问题如何独特而不是重复的问题:我的限制较少:我根本不打算处理这个问题:我只想忽略它并继续前进。首先实际上避免ghostscript中的段错误的任何要点也将受到好评。

这个问题有点老了,但我想我应该分享一下:我正在观看一个关于一个很酷的新内存分配器的视频,在观众提出的一个问题上,作者解释说他“安装了一个段错误处理程序",这是我非常感兴趣的。我仍然不知道他到底是怎么做到的,所以这并不能完全回答我的问题,但它给了我一个开始研究的好地方。如果我自己能解决这个问题,我会在这里发布答案。

这是视频(链接在他回答我正在谈论的问题时) https://youtu.be/c1UBJbfR-H0?t=2058

【问题讨论】:

  • 我认为你不能忽视它。您的代码试图访问不属于它的内存。在这种情况下,它应该立即被操作系统杀死。
  • 是的,您可以捕获它,但您无法从中恢复。实际上,这是您最少的问题之一:假设有人创建了一个文件,然后您将其传递给 Ghostscript。 Ghostscript 有某种缓冲区溢出或类似的错误,然后导致攻击者接管您的系统。将不受信任的数据传递给损坏的软件是您的问题。
  • @ForceBru 我在操作系统上计算只是简单地杀死了实际的罪犯(ghostscript 依赖项)并单独留下 python 解释器(这就是像 faulthandler 这样的库能够真正做一些事情的原因退出前收到信号后的东西)。我的假设错了吗?
  • @CássioRenan,您将如何(以及为什么)检测和隔离负责的图书馆?一切都由 Python 解释器执行,而解释器与操作系统交互,所以被杀死的是解释器。
  • 您可能希望将 Ghostscript 作为外部进程调用,以便与 Python 隔离。然后,如果它崩溃,Python 将不会被破坏。在进程内运行它意味着你的整个 Python 进程都受到了段错误的影响。

标签: python python-3.x segmentation-fault ghostscript


【解决方案1】:

我遇到了类似的问题,通过 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() 将导致段错误的文件移动到另一个文件夹中,而没有杀死我的主脚本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 2014-09-28
    • 2015-09-10
    相关资源
    最近更新 更多