Question

J'essaie de vider une liste de tous les threads actifs, y compris la pile actuelle de chacun. Je peux obtenir une liste de tous les threads en utilisant threading.enumerate (), mais je ne peux pas trouver un moyen d’atteindre la pile à partir de là.

Contexte: une application Zope / Plone s’effondre de temps en temps, consomme à 100% du processeur et doit être redémarrée. J'ai l'impression que c'est une boucle qui ne se termine pas correctement, mais je ne peux pas la reproduire dans l'environnement de test pour vérification. J'ai réussi à enregistrer un gestionnaire de signal qui peut être déclenché de l'extérieur, afin que je puisse déclencher du code dès que la situation se reproduit. Si je pouvais vider le stacktrace pour tous les threads actifs, cela me donnerait un indice sur ce qui ne va pas. Le trou fonctionne sous Python 2.4 ...

Toutes les idées sur la manière de tracer des situations telles que celles-ci sont appréciées:)

Salut,    Chriss

Était-ce utile?

La solution

Lorsque vous utilisez Zope, vous souhaitez installer Products.signalstack . / a> ou mr.freeze ; ceux-ci ont été conçus uniquement dans ce but!

Envoyez un signal USR1 à votre serveur Zope qui dumpera immédiatement les traces de pile de tous les threads vers la console. Cela se fera même si tous les threads de Zope sont bloqués.

Sous le capot, ces paquets utilisent indirectement threadframes ; pour les versions Python 2.5 et supérieures, lorsque pas en utilisant Zope, vous pouvez créer la même fonctionnalité à l'aide de la sys._current_frames () pour accéder aux cadres de pile par thread.

À partir de Zope 2.12.5 , cette fonctionnalité est intégrée à Zope lui-même et il n'est plus nécessaire d'installer de paquets supplémentaires.

Autres conseils

Comme le fait remarquer la gigue dans une réponse précédente, sys._current_frames () vous donne ce dont vous avez besoin pour la version 2.5 +. Pour les paresseux, l'extrait de code suivant a fonctionné pour moi et peut vous aider:

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"

Pour Python 3.3 et versions ultérieures, il existe faulthandler .dump_traceback () .

Le code ci-dessous produit une sortie similaire, mais inclut le nom du fil de discussion et pourrait être amélioré pour imprimer davantage d'informations.

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

2.4. Dommage. A partir de Python 2.5, il y a sys._current_frames () .

Vous pouvez toutefois essayer threadframe . Et si le fichier Make vous pose problème, vous pouvez essayer cette setup.py pour threadframe

Exemple de sortie lors de l'utilisation de threadframe

Par souci d'exhaustivité, Products.LongRequestLogger est extrêmement utile pour identifier les goulets d'étranglement et Pour ce faire, il vide les stacktraces à des intervalles spécifiques.

Une ASPN est disponible. Vous pouvez utiliser threading.enumerate () pour obtenir toutes les informations, puis appelez simplement _async_raise () avec une exception appropriée pour forcer le suivi de la pile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top