애플리케이션 충돌을 감지하고 다시 시작하는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/78048

  •  09-06-2019
  •  | 
  •  

문제

XP에서 응용 프로그램 충돌(매번 동일한 '오류' 창 쌍 생성 - 각각 동일한 창 제목 포함)을 감지하고 다시 시작하는 가장 좋은 방법은 무엇입니까?

특히 문제의 시스템이 상당히 오래되었기 때문에 최소한의 시스템 리소스를 사용하는 솔루션에 대해 듣고 싶습니다.

나는 AutoIt과 같은 스크립팅 언어를 사용하려고 생각했습니다(http://www.autoitscript.com/autoit3/), 아마도 몇 분마다 '감지기' 스크립트를 트리거할 수도 있습니다.

Python, Perl, PowerShell 또는 완전히 다른 것에서 이 작업을 수행하는 것이 더 나을까요?

모든 아이디어, 팁 또는 생각을 높이 평가합니다.

편집하다:실제로는 충돌하지 않습니다(예:종료/종료 - @tialaramex에게 감사드립니다).사용자 입력을 기다리는 대화 상자를 표시한 다음 추가 사용자 입력을 기다리는 또 다른 대화 상자를 표시한 다음 실제로 종료됩니다.제가 감지하고 처리하고 싶은 것은 바로 이러한 대화입니다.

도움이 되었습니까?

해결책

결함이 있는 앱을 자식으로 실행하고 기다리는 래퍼 애플리케이션을 만드는 것은 어떻습니까?하위 항목의 종료 코드에 오류가 표시되면 다시 시작하고 그렇지 않으면 종료합니다.

다른 팁

가장 좋은 방법은 명명된 이름을 사용하는 것입니다. 뮤텍스.

  1. 애플리케이션을 시작하세요.
  2. 새로운 이름의 뮤텍스를 생성하고 소유권을 가져옵니다.
  3. 원하는 대로 새 프로세스(스레드가 아닌 프로세스) 또는 새 애플리케이션을 시작하십시오.
  4. 해당 프로세스/애플리케이션에서 뮤텍스를 획득해 보세요.프로세스가 차단됩니다.
  5. 애플리케이션이 완료되면 뮤텍스를 해제합니다(신호를 보냅니다).
  6. "제어" 프로세스는 애플리케이션이 종료되거나 애플리케이션이 충돌하는 경우에만 뮤텍스를 획득합니다.
  7. 뮤텍스를 획득한 후 결과 상태를 테스트합니다.애플리케이션이 충돌한 경우 WAIT_ABANDONED가 됩니다.

설명: 스레드가 뮤텍스를 해제하지 않고 완료되면 이를 기다리고 있는 다른 프로세스가 이를 획득할 수 있지만 반환 값으로 WAIT_ABANDONED를 얻게 됩니다. 즉, 뮤텍스가 포기되고 보호된 섹션의 상태가 안전하지 않을 수 있습니다.

이렇게 하면 두 번째 앱이 뮤텍스를 계속 기다리므로 CPU 주기를 소비하지 않습니다(그리고 이는 운영 체제에서 엄격하게 처리됩니다).

제가 생각하는 가장 큰 문제는 박사님입니다.Watson은 대화 상자를 표시하고 프로세스를 생생하게 유지합니다.

Windows API를 사용하여 자신의 디버거를 작성하고 충돌 응용 프로그램을 실행할 수 있습니다.이렇게하면 다른 디버거가 응용 프로그램의 충돌을 포착하지 못하고 예외 이벤트를 포착 할 수도 있습니다.

샘플 코드를 찾지 못했기 때문에이 파이썬 Quick and Dirty 샘플을 작성했습니다.Debug_event의 선언이 얼마나 강력한 지 잘 모르겠습니다.

from ctypes import windll, c_int, Structure
import subprocess

WaitForDebugEvent = windll.kernel32.WaitForDebugEvent    
ContinueDebugEvent = windll.kernel32.ContinueDebugEvent
DBG_CONTINUE = 0x00010002L    
DBG_EXCEPTION_NOT_HANDLED = 0x80010001L

event_names = {    
    3: 'CREATE_PROCESS_DEBUG_EVENT',
    2: 'CREATE_THREAD_DEBUG_EVENT',
    1: 'EXCEPTION_DEBUG_EVENT',
    5: 'EXIT_PROCESS_DEBUG_EVENT',
    4: 'EXIT_THREAD_DEBUG_EVENT',
    6: 'LOAD_DLL_DEBUG_EVENT',
    8: 'OUTPUT_DEBUG_STRING_EVENT', 
    9: 'RIP_EVENT',
    7: 'UNLOAD_DLL_DEBUG_EVENT',
}
class DEBUG_EVENT(Structure):
    _fields_ = [
        ('dwDebugEventCode', c_int),
        ('dwProcessId', c_int),
        ('dwThreadId', c_int),
        ('u', c_int*20)]

def run_with_debugger(args):
    proc = subprocess.Popen(args, creationflags=1)
    event = DEBUG_EVENT()

    while True:
        if WaitForDebugEvent(pointer(event), 10):
            print event_names.get(event.dwDebugEventCode, 
                    'Unknown Event %s' % event.dwDebugEventCode)
            ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)
        retcode = proc.poll()
        if retcode is not None:
            return retcode

run_with_debugger(['python', 'crash.py'])

귀하가 Windows XP를 다루고 있다는 것을 알고 있지만 Vista에서 비슷한 상황에 처한 사람들을 위해 새로운 방법이 있습니다. 충돌 복구 API이용 가능합니다. 좋은 소개네요 그들이 무엇을 할 수 있는지.

다음은 약간 개선된 버전입니다.

내 테스트에서 이전 코드는 잘못된 exe가 "액세스 위반"을 생성할 때 무한 루프에서 실행되었습니다.

어떤 예외를 계속해야 하는지, 어떤 예외를 계속할 수 없는지 알 수 있는 명확한 기준이 없기 때문에 내 솔루션이 완전히 만족스럽지 않습니다(ExceptionFlags는 도움이 되지 않습니다).

하지만 제가 실행한 예제에서는 작동합니다.

도움이되기를 바랍니다. Vivian de Smedt

from ctypes import windll, c_uint, c_void_p, Structure, Union, pointer
import subprocess

WaitForDebugEvent = windll.kernel32.WaitForDebugEvent
ContinueDebugEvent = windll.kernel32.ContinueDebugEvent
DBG_CONTINUE = 0x00010002L
DBG_EXCEPTION_NOT_HANDLED = 0x80010001L

event_names = {
    1: 'EXCEPTION_DEBUG_EVENT',
    2: 'CREATE_THREAD_DEBUG_EVENT',
    3: 'CREATE_PROCESS_DEBUG_EVENT',
    4: 'EXIT_THREAD_DEBUG_EVENT',
    5: 'EXIT_PROCESS_DEBUG_EVENT',
    6: 'LOAD_DLL_DEBUG_EVENT',
    7: 'UNLOAD_DLL_DEBUG_EVENT',
    8: 'OUTPUT_DEBUG_STRING_EVENT',
    9: 'RIP_EVENT',
}

EXCEPTION_MAXIMUM_PARAMETERS = 15

EXCEPTION_DATATYPE_MISALIGNMENT  = 0x80000002
EXCEPTION_ACCESS_VIOLATION       = 0xC0000005
EXCEPTION_ILLEGAL_INSTRUCTION    = 0xC000001D
EXCEPTION_ARRAY_BOUNDS_EXCEEDED  = 0xC000008C
EXCEPTION_INT_DIVIDE_BY_ZERO     = 0xC0000094
EXCEPTION_INT_OVERFLOW           = 0xC0000095
EXCEPTION_STACK_OVERFLOW         = 0xC00000FD


class EXCEPTION_DEBUG_INFO(Structure):
    _fields_ = [
        ("ExceptionCode", c_uint),
        ("ExceptionFlags", c_uint),
        ("ExceptionRecord", c_void_p),
        ("ExceptionAddress", c_void_p),
        ("NumberParameters", c_uint),
        ("ExceptionInformation", c_void_p * EXCEPTION_MAXIMUM_PARAMETERS),
    ]

class EXCEPTION_DEBUG_INFO(Structure):
    _fields_ = [
        ('ExceptionRecord', EXCEPTION_DEBUG_INFO),
        ('dwFirstChance', c_uint),
    ]

class DEBUG_EVENT_INFO(Union):
    _fields_ = [
        ("Exception", EXCEPTION_DEBUG_INFO),
    ]

class DEBUG_EVENT(Structure):
    _fields_ = [
        ('dwDebugEventCode', c_uint),
        ('dwProcessId', c_uint),
        ('dwThreadId', c_uint),
        ('u', DEBUG_EVENT_INFO)
    ]

def run_with_debugger(args):
    proc = subprocess.Popen(args, creationflags=1)
    event = DEBUG_EVENT()

    num_exception = 0

    while True:
        if WaitForDebugEvent(pointer(event), 10):
            print event_names.get(event.dwDebugEventCode, 'Unknown Event %s' % event.dwDebugEventCode)

            if event.dwDebugEventCode == 1:
                num_exception += 1

                exception_code = event.u.Exception.ExceptionRecord.ExceptionCode

                if exception_code == 0x80000003L:
                    print "Unknow exception:", hex(exception_code)

                else:
                    if exception_code == EXCEPTION_ACCESS_VIOLATION:
                        print "EXCEPTION_ACCESS_VIOLATION"

                    elif exception_code == EXCEPTION_INT_DIVIDE_BY_ZERO:
                        print "EXCEPTION_INT_DIVIDE_BY_ZERO"

                    elif exception_code == EXCEPTION_STACK_OVERFLOW:
                        print "EXCEPTION_STACK_OVERFLOW"

                    else:
                        print "Other exception:", hex(exception_code)

                    break

            ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)

        retcode = proc.poll()
        if retcode is not None:
            return retcode

run_with_debugger(['crash.exe'])
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top