Отключить автоматическую обработку ошибок Windows в подпроцессах - PullRequest
2 голосов
/ 17 сентября 2010

Я пытаюсь написать набор тестов для компилятора (LLVM), и он прекрасно работает на любой платформе, кроме Windows.В Windows я получаю окно сообщения «обработчик критической ошибки», которое останавливает тесты на неопределенное время.

Эта проблема делает тестирование очень трудным, потому что с компиляторами проблема часто означает недопустимый код на уровне сборки,и, следовательно, сумасшедшие, непредсказуемые ошибки.

Я обнаружил Во время вызова подпроцесса перехватывайте критические ошибки Windows в Python вместо того, чтобы позволить ОС обрабатывать их, показывая всплывающие окна с ошибками во время поискаответ, но это не работает для меня.Я все еще получаю окна сообщений при тестировании.

Документация по [SetErrorMode] (http://msdn.microsoft.com/en-us/library/ms680621(VS100).aspx) говорит, что:

SEM_FAILCRITICALERRORS:
Система не отображаетсяокно сообщения обработчика критических ошибок. Вместо этого система отправляет ошибку вызывающему процессу.

SEM_NOGPFAULTERRORBOX:
Система не отображает диалоговое окно отчетов об ошибках Windows.

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

Однако после вызова SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)и запуская процесс с CreateProcess с dwCreationFlags = CREATE_NEW_CONSOLE, я все еще получаю коробки, когда подпроцессы терпят неудачу.

В случае, если это имеет значение, точный код Python, который я использую:

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

Как мне это исправить?

Ответы [ 2 ]

0 голосов
/ 18 сентября 2010

Проблема на самом деле была у доктора Ватсона (ссылка отредактирована), который грубо игнорирует SetErrorMode (ссылка отредактирована). Единственный способ помешать доктору Уотсону украсть вашу радость - это не дать ему когда-либо позвонить. Есть два способа сделать это.

  1. Звоните SetUnhandledExceptionHandler(yourexceptionhandler);

    Если вы вызываете exit в этом обработчике, программа завершается нормально, и доктор Ватсон никогда не вызывается.

    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 (ссылка удалена)

    При запуске процесса, подобного этому, все исключения передаются в отладчик, и, таким образом, они могут обрабатываться соответствующим образом.

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

0 голосов
/ 17 сентября 2010

Режим ошибки обычно наследуется подпроцессами. Это звучит как реализация system (или execv, или что-то еще используемое для порождения подпроцессов) передает флаг CREATE_DEFAULT_ERROR_MODE, когда он вызывает CreateProcess. Чтобы получить желаемое поведение (наследование установленного вами режима ошибки), вам нужно либо изменить реализацию библиотеки, чтобы все, что вы используете для запуска процессов, не проходило под этим флагом, либо реализовать (и использовать ) что-то новое, что не проходит мимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...