Modo migliore per individuare un crash dell'applicazione e riavviare?
-
09-06-2019 - |
Domanda
Qual è il modo migliore per rilevare un crash dell'applicazione in XP (produce la stessa coppia di "errore" windows ogni volta - ogni con lo stesso titolo della finestra) e poi riavviare?
Sono particolarmente interessato a sentire le soluzioni che utilizzano le risorse di sistema minime in quanto il sistema in questione è abbastanza vecchio.
Avevo pensato di usare un linguaggio di scripting come AutoIt (http://www.autoitscript.com/autoit3/), e, forse, l'attivazione di un 'rivelatore' script ogni pochi minuti?
Sarebbe meglio se fatto in Python, Perl, PowerShell o qualcosa di completamente diverso?
Idee, suggerimenti, o pensieri molto apprezzato.
EDIT:In realtà, non crash (es.uscita/fine - grazie @tialaramex).Visualizza una finestra di dialogo in attesa dell'input dell'utente, seguito da un'altra finestra in attesa di ulteriori input dell'utente, quindi termina effettivamente.Queste finestre di dialogo che vorrei rilevare e trattare.
Soluzione
Come circa la creazione di un wrapper applicazione che lancia il difettoso app come un bambino e si aspetta?Se il codice di uscita del bambino indica un errore, riavviare, altrimenti esci.
Altri suggerimenti
Modo migliore è quello di utilizzare un nome mutex.
- Avviare l'applicazione.
- Creare un nuovo mutex denominato e prendere la proprietà su di esso
- Avviare un nuovo processo (processo non thread) o una nuova applicazione, che si preffer.
- Da tale processo / applicazione tenta di acquisire il mutex.Il processo di blocco
- Quando l'applicazione di finitura rilascia il mutex (segnale)
- Il "controllo" del processo solo acquisire il mutex se l'applicazione di finiture o l'applicazione si blocca.
- Prova lo stato risultante dopo acquisendo il mutex.Se la domanda era schiantato sarà WAIT_ABANDONED
Spiegazione: Quando un thread termina senza rilasciare il mutex qualsiasi altro processo in attesa che si possono acquisire, ma è ottenere un WAIT_ABANDONED come valore di ritorno, il che significa che il mutex viene abbandonato e pertanto lo stato della sezione è stato protetto può essere pericoloso.
In questo modo la tua seconda applicazione non consuma cicli di CPU come sarà tenere d'attesa per il mutex (e che è interamente gestita dal sistema operativo)
Credo che il problema principale è che il Dr.Watson visualizza una finestra di dialogo e mantiene il vostro processo di vita.
È possibile scrivere il proprio debugger utilizzando le API di Windows e eseguire il crash dell'applicazione da lì.Questo consentirà di evitare altri debugger, da dove prendere il crash di la domanda e si potrebbe anche prendere l'evento di Eccezione.
Dato che non ho trovato nessun codice di esempio, ho scritto questo Python quick-and-dirty campione.Io non sono sicuro di come robusto è in particolare la dichiarazione di DEBUG_EVENT potrebbe essere migliorata.
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'])
Mi rendo conto che hai a che fare con Windows XP, ma per le persone in una situazione simile in Vista, ci sono nuovi crash recovery APIs disponibili. Ecco una buona introduzione quello che possono fare.
Qui è una versione leggermente migliorata.
Nel mio test precedente l'esecuzione di codice in un ciclo infinito quando il guasto exe generato una "violazione di accesso".
Io non sono completamente soddisfatto con la mia soluzione, perché non ho criteri chiari per sapere quali eccezione deve essere continuato e che non si potrebbe essere (Il ExceptionFlags non è di nessun aiuto).
Ma funziona su l'esempio che ho eseguito.
Speranza che aiuta, 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'])