2011-01-22 10 views
5

Sé que puedo obtener el seguimiento de la pila del hilo actual utilizando backtrace() o [NSThread callStackSymbols], pero ¿cómo puedo obtener el rastro de pila de un hilo DIFERENTE (suponiendo que ha sido congelado)?Imprimir un seguimiento de pila de otro hilo

Respuesta

10

EDITAR: Mi respuesta original no se imprime desde un hilo arbitrario. desde que he escrito una correcta aplicación en mi proyecto manejador de fallos: https://github.com/kstenerud/KSCrash

En concreto, estos archivos:

con la ayuda de:

Lo que se hace es:

  • hacer una nueva estructura de contexto máquina (_STRUCT_MCONTEXT)
  • introducir en su estado de pila usando thread_get_state()
  • Consigue el contador de programa (primera entrada de seguimiento de pila) y puntero de marco (todo el resto)
  • Atraviesa el marco de pila apuntado por el puntero de marco y almacena todas las instrucciones a cambios en un búfer para su uso posterior.

Tenga en cuenta que debe pausar el hilo antes de hacer esto o puede obtener resultados impredecibles.

El marco de pila está llena de estructuras que contienen dos punteros:

  • puntero al siguiente nivel hacia arriba en la pila
  • dirección de la instrucción

Así que hay que tener esto en cuenta a la hora caminando por el marco para completar tu rastro de pila. También existe la posibilidad de una pila corrupta, lo que lleva a un puntero malo, que bloqueará su programa. Puede evitar esto copiando memoria usando vm_read_overwrite(), que primero le pregunta al kernel si tiene acceso a la memoria, para que no se cuelgue.

Una vez que tenga el seguimiento de pila, puede simplemente llamar a backtrace() como normal (el controlador de bloqueo debe ser asincrónico para que implemente su propio método de rastreo, pero en casos normales backtrace() está bien) .

+0

Tenga en cuenta que debe suspender el hilo mientras lee su pila. – Albert

+0

Además, ¿estás seguro de que esto funciona? Utiliza '__builtin_frame_address', que siempre trata sobre el hilo ** actual **. – Albert

+0

Resulta que esto realmente no funciona (imprime un seguimiento de la pila, pero no me di cuenta de que estaba imprimiendo desde el hilo actual). Tengo un código nuevo que funciona según lo previsto, pero aún no está listo para su lanzamiento. Publicaré una actualización una vez que esté lista. – Karl

3

Aquí hay una forma más segura de obtener la pila de llamada de otra secuencia: Implementation y some background information. Utiliza el manejo de señal y genera un manejador de señal en el hilo objetivo. También tiene la ventaja de que es más multiplataforma que su solución, es decir, debería funcionar en cualquier lugar donde tenga <signal.h> y <execinfo.h>. Para imprimir, puede usar backtrace_symbols como lo hace en su propia sugerencia. Pero puede que le interese una versión extendida de eso según lo implementado here.Utiliza libbfd (desde binutils; la versión más reciente también funciona principalmente en MacOSX, consulte here para una pequeña limitación que puede no ser relevante para usted) para leer la información de depuración y para agregar el número de línea y otra información (también recae en dladdr si falla todo lo demás; eso es lo que está haciendo backtrace_symbols).

Cuestiones relacionadas