2010-12-07 44 views
23

J'ai un processus qui est appelé par un autre processus qui est appelé par un autre processus et ainsi de suite ad nauseum. C'est un processus enfant dans une longue chaîne d'outils.Existe-t-il un moyen de dire à gdb d'attendre le début et la fixation d'un processus?

Ce processus plante.

Je voudrais attraper ce processus dans gdb pour comprendre pourquoi il plante. Cependant, la seule façon dont je peux penser est:

  1. démarrer le processus parent d'origine dans la ligne de commande.
  2. interrogez ps -C <name process I want to catch> et obtenez le PID.
  3. lancement gdb, attaché à PID de ce processus.

Ceci est fastidieux, mais généralement fait le travail. Le problème est que la panne actuelle s'exécute très rapidement, et au moment où je capture le PID et lance gdb, il a déjà passé le point de défaillance.

Je voudrais lancer gdb et au lieu de:

(gdb) attach <pid> 

Je voudrais faire:

(gdb) attach <process name when it launches> 

Est-il possible de le faire?


J'utilise gdb 7.1 sur linux

Répondre

5

Vous pouvez joindre à un processus parent et ensemble suivi fork mode enfant. Cela fera gdb déboguer le processus enfant au lieu du parent après le forking. Aussi fourche de capture sera utile. Cela fera arrêter gdb après chaque fork. Voir docs.

+0

Mais cela peut devenir assez fastidieux si l'arbre de processus est profond (comme c'est dans mon cas) –

+0

@NathanFellman - Une solution à l'ennui pourrait être d'écrire du code d'extension Python pour gdb qui automatise ce processus. Il pourrait se réveiller après chaque fourchette prise, déterminer si cette fourchette est pertinente, puis continuer si ce n'est pas le cas. – Omnifarious

1

Pas exactement ce que vous attendez, mais cela pourrait vous aider dans le débogage.

valgrind --trace-children=yes your_program 

va vérifier et imprimer des erreurs de mémoire dans tous les enfants du processus, avec trace de la pile et quelques détails sur l'erreur (par exemple. En cas de double-free, vous obtiendrez la trace de la pile de la première libre). De plus, vous pouvez faire en sorte que le processus de plantage génère une image mémoire de base et débogue ce post-mortem. Voir this answer for details.

8

Sous Mac OS X, vous pouvez utiliser:

(gdb) attach --waitfor <process-name> 

mais cela est parfois incapable de saisir les processus qui sortent très rapidement. Je ne sais pas si cela est pris en charge sur d'autres plates-formes.

GDB Release Notes for Mac OS X v10.5 WWDC Seed

+0

Voilà ce que je cherche. Malheureusement, il semble être non pris en charge dans ma version (7.2) –

+0

ainsi que dans la version 7.3.1 –

+2

Utiliser gdb-apple: port sudo installer gdb-apple –

1

J'ai été confronté à un problème similaire avec quelque chose que je suis en train de debug, et je suis venu avec une solution à l'aide ldpreload, mais après avoir vu Joeys réponse, je pense que je vais essayer d'abord.Si c'est utile à quelqu'un d'autre, voici l'idée:

Créez une bibliothèque LD_PRELOAD pour connecter les appels exec * (il y a beaucoup de guides sur la façon de faire cela, mais si je le fais, je mettrai ma réponse à jour avec le code), vérifiez le chemin utilisé lors du passage de l'appel exec *, si c'est notre cible, puis envoyez un message avec le PID à stderr et passez dans une boucle infinie (avec sleep pour éviter une utilisation massive du CPU). Ensuite, vous pouvez attacher avec gdb et modifier le registre utilisé dans la boucle pour continuer l'exécution.

Cela peut impliquer un ASM en ligne pour s'assurer que le compilateur n'optimise pas la boucle infinie de telle sorte qu'il est difficile de sortir de cette boucle. Une manière plus éloquente de le faire serait de trouver un moyen de détecter que gdb est attaché puis de déclencher un point d'arrêt ("asm (" int3 ");" devrait faire l'affaire sur ce dernier).

15

Voici mon script appelé gdbwait:

#!/bin/sh 
progstr=$1 
progpid=`pgrep -o $progstr` 
while [ "$progpid" = "" ]; do 
    progpid=`pgrep -o $progstr` 
done 
gdb -ex continue -p $progpid 

Utilisation:

gdbwait my_program 

Bien sûr, il peut être écrit plus agréable, mais la syntaxe de script shell Bourne est douloureux pour moi si cela fonctionne alors je laisse seul. :) Si le nouveau processus démarre et meurt trop rapidement, ajoutez 1 seconde de retard dans votre propre programme pour le débogage ...

+0

merci. c'est très utile. –