Dump stacktraces di tutti i thread attivi
-
06-07-2019 - |
Domanda
Sto cercando di scaricare un elenco di tutti i thread attivi incluso lo stack corrente di ciascuno. Posso ottenere un elenco di tutti i thread usando threading.enumerate (), ma non riesco a trovare un modo per arrivare allo stack da lì.
Sfondo: un'app Zope / Plone si spaventa di tanto in tanto, consumando il 100% della CPU e deve essere riavviata. Ho la sensazione che sia un ciclo che non termina correttamente, ma non riesco a riprodurlo nell'ambiente di test per la verifica. Sono riuscito a registrare un gestore di segnale che può essere attivato dall'esterno, quindi posso attivare un po 'di codice non appena la situazione si ripresenta. Se potessi scaricare lo stacktrace per tutti i thread attivi, questo mi darebbe un indizio su cosa vada storto. La cosa del buco gira su Python 2.4 ...
Le idee su come rintracciare situazioni come queste sono apprezzate :)
Saluti, Chriss
Soluzione
Quando si utilizza Zope, si desidera installare Products.signalstack
o mr.freeze ; questi sono stati progettati proprio per questo scopo!
Invia un segnale USR1 al tuo server Zope e scaricherà immediatamente le tracce dello stack per tutti i thread sulla console. Lo farà anche se tutti i thread di Zope sono bloccati.
Questi pacchetti usano indirettamente threadframes
; per Python versione 2.5 e successive, quando non usando Zope, puoi costruire la stessa funzionalità usando sys._current_frames ()
per accedere ai frame dello stack per thread.
A partire da Zope 2.12.5 questa funzionalità è integrata in Zope stessa e non è più necessario installare pacchetti aggiuntivi.
Altri suggerimenti
Come indica il jitter in una risposta precedente sys._current_frames ()
ti dà ciò di cui hai bisogno per v2.5 +. Per i più pigri il seguente frammento di codice ha funzionato per me e può aiutarti:
print >> sys.stderr, "\n*** STACKTRACE - START ***\n"
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# ThreadID: %s" % threadId)
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename,
lineno, name))
if line:
code.append(" %s" % (line.strip()))
for line in code:
print >> sys.stderr, line
print >> sys.stderr, "\n*** STACKTRACE - END ***\n"
Per Python 3.3 e versioni successive, esiste faulthandler .dump_traceback ()
.
Il codice seguente produce un output simile, ma include il nome del thread e potrebbe essere migliorato per stampare più informazioni.
for th in threading.enumerate():
print(th)
traceback.print_stack(sys._current_frames()[th.ident])
print()
2.4. Peccato. Da Python 2.5 in poi c'è sys._current_frames ()
.
Ma potresti provare threadframe . E se il makefile ti dà problemi potresti provare questo setup.py per threadframe
Solo per completezza, Products.LongRequestLogger è super utile per identificare i colli di bottiglia e per fare ciò scarica stacktraces a intervalli specifici.
Esiste una ricetta applicabile su ASPN . Puoi usare threading.enumerate ()
per ottenere tutte le maree, quindi chiama _async_raise () con qualche eccezione adatta per forzare una traccia dello stack.