Obtenir la trace de tous les threads sans attacher GDB

Existe-t-il un moyen d’imprimer le stacktrace de tous les threads sans joindre GDB?

Ou existe-t-il une commande que je peux utiliser comme mode batch gdb pour imprimer le stacktrace de tous les threads?

Il y a un thread apply all commandes dans GDB:

 (gdb) thread apply all bt Thread 12 (Thread 0x7f7fe2116700 (LWP 5466)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000425358 in ?? () ... Thread 1 (Thread 0x7f7feabc27c0 (LWP 5465)): #0 0x00007f7fe76c5203 in select () at ../sysdeps/unix/syscall-template.S:82 

Malheureusement, GDB ne semble pas être en mesure de lire les commandes d’un tube, donc pour exécuter les commandes en mode batch, un fichier temporaire doit être utilisé:

 $ gdbbt() { tmp=$(tempfile) echo thread apply all bt >"$tmp" gdb -batch -nx -q -x "$tmp" -p "$1" rm -f "$tmp" } $ gdbbt $(pidof $SHELL) 

pstack?

Usage:

 pstack  

De la page de manuel:

 pstack - print a stack trace of a running process ... If the process is part of a thread group, then pstack will print out a stack trace for each of the threads in the group. 

J’ai utilisé ceci:

 pidof program | xargs -n1 sudo gdb --batch -ex "thread apply all bt" -p 

Le script suivant fonctionne pour moi sur Linux S’il vous plaît noter qu’il découvre d’abord le répertoire de l’exécutable et les modifications à ce répertoire (parce que exécutable peut avoir des bibliothèques partagées avec chemin relatif en utilisant -Wl, -rpath, $ dir spécifié lors de la liaison et vous voudriez que gdb trouve les symboles pour ces bibliothèques partagées pour la trace de stack). Il suppose également que gdb est présent sur le système.

 #!/bin/bash pid=$1 EXE=`readlink -f /proc/$pid/exe` DIR=`dirname $EXE` cd $DIR gdb $EXE --batch -ex "attach $pid" -ex "thread apply all bt" 

Comme dans linux, tous les threads sont essentiellement des processus légers, ils reçoivent des PID LWP individuels. vous pouvez en sauvegarder le statut en utilisant un script basé sur ps ou top ou en reprenant le w dans /proc/sysrq-sortinggger . Cela vous donnera l’état d’ I/O des threads dans /var/log/messages .

Cela ne vous donnera cependant pas la trace complète de la stack. mais c’est un bon moyen de déboguer les états des threads à intervalles réguliers.

Vous pouvez également explorer l’état actuel du planificateur en consultant /proc/sched_debug pour voir quelles tâches sont planifiées, etc.

elfutils parmi d’autres utilitaires inclut eu-stack :

 eu-stack Print a stack for each thread in a process or core file. 

Il est plus rapide que gdb ou pstack, qui est juste un wrapper de script shell autour de gdb. Pour imprimer les traces de stack, exécutez la commande eu-stack comme suit:

 $ eu-stack -p 2209 PID 2209 - process TID 2209: #0 0x00007f53476b667b __poll #1 0x00007f5348f98e99 g_main_context_iterate.isra.23 #2 0x00007f5348f99232 g_main_loop_run #3 0x000055e604b1e56a main #4 0x00007f53475cc00a __libc_start_main #5 0x000055e604b1e76a _start TID 2223: #0 0x00007f53476b667b __poll #1 0x00007f5348f98e99 g_main_context_iterate.isra.23 #2 0x00007f5348f98fac g_main_context_iteration #3 0x00007f5348f98ff1 glib_worker_main #4 0x00007f5348fc0486 g_thread_proxy #5 0x00007f534813761b start_thread #6 0x00007f53476c2c2f __clone TID 2224: #0 0x00007f53476b667b __poll #1 0x00007f5348f98e99 g_main_context_iterate.isra.23 #2 0x00007f5348f99232 g_main_loop_run #3 0x00007f5349581b56 gdbus_shared_thread_func #4 0x00007f5348fc0486 g_thread_proxy #5 0x00007f534813761b start_thread #6 0x00007f53476c2c2f __clone