Pregunta

Estoy tratando de volcar una lista de todos los hilos activos, incluida la pila actual de cada uno. Puedo obtener una lista de todos los hilos usando threading.enumerate (), pero no puedo encontrar una manera de llegar a la pila desde allí.

Antecedentes: una aplicación Zope / Plone se asusta de vez en cuando, consume el 100% de la CPU y debe reiniciarse. Tengo la sensación de que es un bucle que no termina correctamente, pero no puedo reproducirlo en el entorno de prueba para su verificación. Logré registrar un controlador de señal que se puede activar desde el exterior, por lo que puedo activar un código tan pronto como la situación vuelva a ocurrir. Si pudiera volcar el stacktrace para todos los hilos activos, eso me daría una idea de lo que sale mal. El agujero se ejecuta en Python 2.4 ...

Cualquier idea sobre cómo rastrear situaciones como estas es apreciada :)

Saludos,    Chriss

¿Fue útil?

Solución

Cuando use Zope, desea instalar Products.signalstack o mr.freeze ; ¡Estos fueron diseñados para este propósito!

Envíe una señal USR1 a su servidor Zope e inmediatamente volcará los rastros de la pila para todos los hilos a la consola. Hará esto incluso si todos los hilos de Zope están bloqueados.

Bajo el capó, estos paquetes usan indirectamente threadframes ; para Python versiones 2.5 y posteriores, cuando no usa Zope, puede crear la misma funcionalidad usando sys._current_frames () función para acceder a marcos de pila por subproceso.

A partir de Zope 2.12.5 esta funcionalidad está integrada en el propio Zope, y ya no es necesario instalar paquetes adicionales.

Otros consejos

Como jitter señala en una respuesta anterior, sys._current_frames () le brinda lo que necesita para v2.5 +. Para los perezosos, el siguiente fragmento de código funcionó para mí y puede ayudarlo:

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"

Para Python 3.3 y posterior, hay faulthandler .dump_traceback () .

El siguiente código produce una salida similar, pero incluye el nombre del hilo y podría mejorarse para imprimir más información.

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

2.4. Demasiado. Desde Python 2.5 en adelante hay sys._current_frames () .

Pero podría probar threadframe . Y si el archivo MAKE le causa problemas, puede probar esto setup.py para threadframe

Ejemplo de salida cuando se usa threadframe

Solo por razones de integridad, Products.LongRequestLogger es muy útil para identificar cuellos de botella, y para hacerlo, volcará los stacktraces a intervalos específicos.

Hay una receta aplicable en ASPN . Puede usar threading.enumerate () para obtener todos los tids, luego simplemente llame a _async_raise () con alguna excepción adecuada para forzar un seguimiento de pila.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top