2009-06-23 12 views
26

Ich versuche, eine Liste aller aktiven Threads einschließlich des aktuellen Stapels von jedem zu löschen. Ich kann eine Liste aller Threads mit threading.enumerate() erhalten, aber ich kann keinen Weg finden, von dort zum Stack zu kommen.Dump stacktraces aller aktiven Threads

Hintergrund: Eine Zope/Plone-App flippt von Zeit zu Zeit aus, verbraucht 100% der CPU und muss neu gestartet werden. Ich habe das Gefühl, dass es eine Schleife ist, die nicht ordnungsgemäß beendet wird, aber ich kann sie nicht in der Testumgebung zur Verifikation reproduzieren. Es ist mir gelungen, einen Signal-Handler zu registrieren, der von außen ausgelöst werden kann, so dass ich Code auslösen kann, sobald die Situation wieder auftritt. Wenn ich den StackTrace für alle aktiven Threads ausgeben könnte, würde ich einen Hinweis bekommen, was schief läuft. Das Loch, was läuft auf Python 2.4 ...

Alle Ideen, wie Situationen wie diese zurückzuverfolgen sind willkommen :)

Cheers, Chriss

Antwort

8

Wenn Zope verwenden, möchten Sie Products.signalstack oder mr.freeze installieren; Diese wurden nur für diesen Zweck entwickelt!

Senden Sie ein USR1-Signal an Ihren Zope-Server, und es werden sofort Stack-Traces für alle Threads an die Konsole ausgegeben. Es wird dies tun, selbst wenn alle Zope-Threads gesperrt sind.

Unter der Haube verwenden diese Pakete indirekt threadframes; für Python-Versionen 2.5 und höher, wenn nicht mit Zope verwenden, können Sie die gleiche Funktionalität mit der sys._current_frames()-Funktion für den Zugriff auf Thread-Stack-Frames erstellen.

Ab Zope 2.12.5 ist diese Funktionalität in Zope selbst integriert und es müssen keine zusätzlichen Pakete mehr installiert werden.

+0

Vielen Dank, das ist genau das, was ich brauche! – Chriss

+0

Heutzutage in Plone "keine speziellen Pakete sind notwendig" http: // stackoverflow.com/a/36633215/3046069 – Danimal

+0

@Danimal: danke, hinzugefügt, um den Beitrag. 2.12.5 wurde ein Jahr nachdem ich diese Antwort geschrieben hatte veröffentlicht. –

0

Es ist ein anwendbares Rezept auf ASPN. Sie können threading.enumerate() verwenden, um alle TIDs zu erhalten, und dann einfach _async_raise() mit einer geeigneten Ausnahme aufrufen, um eine Stack-Trace zu erzwingen.

35

Wie Jitter in einer früheren Antwort zeigt sys._current_frames() gibt Ihnen, was Sie für v2.5 + brauchen. Für die Faulen der folgende Code-Schnipsel für mich gearbeitet und Sie können helfen:

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" 
13

für Python 3.3 und später ist es faulthandler.dump_traceback().

Der folgende Code erzeugt eine ähnliche Ausgabe, enthält jedoch den Namen des Threads und könnte erweitert werden, um weitere Informationen zu drucken.

for th in threading.enumerate(): 
    print(th) 
    traceback.print_stack(sys._current_frames()[th.ident]) 
    print() 
1

Nur der Vollständigkeit halber willen, ist Products.LongRequestLogger Super hilfreich Engpässe zu identifizieren und zu tun, damit es stacktraces in bestimmten Abständen Dumps.

Verwandte Themen