2011-06-19 13 views
16

En Linux, para obtener una traza inversa, puede usar la llamada a la biblioteca backtrace(), pero solo devuelve la traza inversa del hilo actual. ¿Hay alguna forma de obtener un rastreo de otro hilo, suponiendo que sé que es TID (o pthread_t) y puedo garantizar que duerma?Obtener un rastreo de otro hilo

Parece que el proyecto libunwind (http://www.nongnu.org/libunwind/) puede ayudar. El problema es que no es compatible con CentOS, por lo que prefiero no usarlo.

¿Alguna otra idea? Gracias.

Respuesta

7

El manejo de señales con la ayuda de la traza inversa puede resolver su propósito.

Quiero decir que si tiene un PID del hilo, puede generar una señal para ese hilo. y en el controlador puedes usar la traza inversa. dado que el controlador se estaría ejecutando en ese subproceso particular, la traza inversa allí sería la salida que se necesita.

+1

Esto no es precisamente lo que estaba buscando, pero esta es una buena idea. Creo que puedo usarlo ¡Gracias! –

+0

@Alexander es esta solución que funciona para usted cuando malloc o llamadas gratuitas son llamadas de pila ..? y ¿puede llamar a backtrace() en este caso desde el controlador de señal? Me estoy rompiendo. – sandeep

+0

Eventualmente, decidí trabajar con libunwind. Esta solución es demasiado complicada para mis circunstancias y decidí abandonarla. De todos modos, publique aquí si lo hace funcionar de alguna manera. –

8

Lo implementé yo mismo here.

Inicialmente, quería implementar algo similar a here sugerido, es decir, obtener de algún modo el puntero de marco superior de la hebra y desenrollarlo manualmente (la fuente vinculada se deriva de la implementación de Applus backtrace, por lo que podría ser específica de Apple, pero la idea es genérica).

Sin embargo, para tener esa seguridad (y la fuente de arriba no es e incluso puede romperse), debe suspender el hilo mientras accede a su pila. Busqué diferentes formas de suspender un hilo y encontré this, this y this. Básicamente, no hay una manera realmente buena. El truco común, también used by the Hotspot JAVA VM, es usar señales y enviar una señal personalizada a su hilo a través del pthread_kill.

Así que, como necesitaría tal señal-hack de todos modos, puedo tenerlo un poco más simple y simplemente usar backtrace dentro del controlador de señal llamado que se ejecuta en el hilo objetivo (como también se sugirió here by sandeep). Esto es básicamente lo que está haciendo mi implementación.

Si también está interesado en imprimir la traza inversa, es decir, obtener alguna información de depuración (nombre de la función, el nombre de archivo de código fuente, fuente de número de línea de código, ...), leer here acerca de un prolongado backtrace_symbols basado en libbfd. O simplemente vea la fuente here.

+1

Albert, tengo un escenario en el que necesito obtener la pila de llamadas del hilo principal desde el hilo de fondo. La idea detrás de esto es que si hay un bloqueo en el subproceso de la IU de más de 2 segundos, el hilo de fondo que supervisa el hilo de la IU cada 200 ms recogerá la pila de llamadas. Me preguntaba si su solución también podría abordar esta. Muchas gracias por adelantado. –

+0

@ilkerAcar: Sí, la función 'int GetCallstack (ThreadId threadId, void ** buffer, int size)' en mi implementación se puede invocar desde cualquier hilo. Solo pase la identificación del hilo principal. – Albert

+0

Por cierto, también estoy haciendo esto en algún proyecto, vea 'startMainLockDetector()' [aquí] (https://github.com/albertz/openlierox/blob/0.59/src/MainLoop.cpp). – Albert

0

BGF proporciona estas instalaciones para la depuración de programas multi-hilo:

  • notificación automática de nuevos temas
  • 'hilo de rosca-id', un comando para cambiar entre los hilos
  • 'Hilos Información', un comando para preguntar acerca de los hilos existentes
  • 'thread apply [lista-id-hilo] [todos] args', un comando para aplicar un comando a una lista de hilos
  • puntos de corte específicos de hilo
  • 'set print thread-events', que controla la impresión de mensajes en el inicio y la salida del hilo.
  • 'set libthread-db-search-path path', que le permite al usuario especificar qué libthread_db usar si la opción predeterminada no es compatible con el programa.

Así que simplemente goto requiere hilo en GDB por cmd: 'thread thread-id'. Luego, haga 'bt' en ese contexto de subproceso para imprimir la traza inversa del subproceso.

Cuestiones relacionadas