Skip to main content
 首页 » 编程设计

python之禁用 Window 自动处理子进程中的错误

2025年05月04日9dyllove98

我正在尝试为编译器 (LLVM) 编写测试套件,它在除 Windows 之外的所有平台上都运行良好。在 Windows 上,我收到“严重错误处理程序”消息框,它会无限期地停止测试。

这个问题使得测试变得非常困难,因为对于编译器,问题通常意味着汇编级别的无效代码,从而导致疯狂的、不可预测的错误。

我找到了 During a subprocess call, catch critical windows errors in Python instead of letting the OS handle it by showing nasty error pop-ups在寻找答案时,但这对我不起作用。测试时我仍然会收到消息框。

关于 [SetErrorMode]( http://msdn.microsoft.com/en-us/library/ms680621(VS100).aspx) 的文档说:

SEM_FAILCRITICALERRORS:
The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.

SEM_NOGPFAULTERRORBOX:
The system does not display the Windows Error Reporting dialog.

Each process has an associated error mode that indicates to the system how the application is going to respond to serious errors. A child process inherits the error mode of its parent process.

然而,在调用 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX) 并使用 CreateProcess 和 dwCreationFlags = CREATE_NEW_CONSOLE 启动进程后,我仍然得到这些框当子流程失败时。

以防万一,我使用的确切 Python 代码是:

import ctypes 
# 3 is SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX 
ctypes.windll.kernel32.SetErrorMode(3) 

我该如何解决?

请您参考如下方法:

问题实际上是 Watson 博士(链接已编辑),他粗鲁地忽略了 SetErrorMode(链接已编辑)。防止 Watson 医生偷走您的快乐的唯一方法是永远不让他接到电话。有两种方法可以做到这一点。

  1. 调用SetUnhandledExceptionHandler(yourexceptionhandler);

    如果您在此处理程序中调用 exit,程序将正常终止并且永远不会调用 Dr. Watson。

    UnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 
      fputs("Application crashed with unhandled exception!\n", stderr); 
     
      // Exit to prevent anything else from handling this exception. 
      _exit(-3); 
    } 
     
    int main() { 
      SetUnhandledExceptionFilter(UnhandledExceptionFilter); 
    } 
    

    这仅在您有权访问源代码并想对其进行修改时才有效。在我的例子中,我可以访问源代码,但它是几百个独立文件的集合,因此在所有这些文件中添加这段代码是不可能的。它也不会处理 main 之前的错误,或者只是简单的无效可执行文件。

  2. 使用 CreateProcess(..., DEBUG_PROCESS, ...)(已编辑链接)和 WaitForDebugEvent(已编辑链接)在调试器下运行进程

    当运行这样的进程时,所有异常都会传播到调试器,因此它们可以得到适当的处理。

    对于本来应该很简单的问题来说,这是一个相当复杂的解决方案,但这是我发现的完全阻止 Dr. Watson 的唯一方法。我目前正在编写一个最小的程序,它试图以各种方式正常运行子进程,除了捕获未处理的异常。一旦提交,我将在此处发布链接。