Il est souvent utile de suivre une pile de thread de processus au moment précis de l'activation d'une sonde pour examiner un problème plus en détails. L'action de la fonction ustack() suit la pile du thread utilisateur. Si, par exemple, un processus ouvrant plusieurs fichiers rencontre occasionnellement une défaillance dans l'appel système open(2), vous pouvez utiliser l'action de la fonction ustack() pour rechercher le chemin d'accès au code exécutant la fonction open() en échec :
syscall::open:entry /pid == $1/ { self->path = copyinstr(arg0); } syscall::open:return /self->path != NULL && arg1 == -1/ { printf("open for '%s' failed", self->path); ustack(); }
Ce script illustre également l'utilisation de la variable de macro $1 qui récupère la valeur du premier opérande spécifié sur la ligne de commande de dtrace(1M).
# dtrace -s ./badopen.d 31337 dtrace: script './badopen.d' matched 2 probes CPU ID FUNCTION:NAME 0 40 open:return open for '/usr/lib/foo' failed libc.so.1`__open+0x4 libc.so.1`open+0x6c 420b0 tcsh`dosource+0xe0 tcsh`execute+0x978 tcsh`execute+0xba0 tcsh`process+0x50c tcsh`main+0x1d54 tcsh`_start+0xdc |
L'action de la fonction ustack() enregistre les valeurs (PC) du compteur du programme pour la pile et dtrace(1M) résout ces valeurs PC pour symboliser les noms en effectuant une recherche dans les tables des symboles du processus. Si dtrace ne parvient pas à retrouver le symbole d'une valeur PC, cette dernière est imprimée sous la forme d'un entier hexadécimal.
Si un processus se termine ou est avorté avant le formatage final des données de la fonction ustack(), dtrace risque de ne pas pouvoir convertir les valeurs PC du suivi de pile en noms de symbole et devra les afficher sous forme de nombres hexadécimaux. Pour contourner cette restriction, spécifiez un processus qui vous intéresse avec l'option -dtrace -c ou p. Pour plus d'informations sur ces options (et bien d'autres), reportez-vous au Chapitre14Utilitaire dtrace(1M). En cas d'ignorance préalable de la commande ou de l'ID de processus, vous pouvez utiliser l'exemple suivant de programme en D pour contourner cette restriction :
/* * This example uses the open(2) system call probe, but this technique * is applicable to any script using the ustack() action where the stack * being traced is in a process that may exit soon. */ syscall::open:entry { ustack(); stop_pids[pid] = 1; } syscall::rexit:entry /stop_pids[pid] != 0/ { printf("stopping pid %d", pid); stop(); stop_pids[pid] = 0; }
Le script ci-dessus interrompt un processus juste avant qu'il ne se termine si l'action de la fonction ustack() a été appliquée à un thread dans ce processus. Grâce à cette technique, la commande dtrace peut résoudre les valeurs PC en noms symboliques. Notez que la valeur de stop_pids[pid] est réglée sur 0 après avoir servi à supprimer la variable dynamique. N'oubliez pas de configurer la réexécution des processus interrompus à l'aide de la commande prun(1). Dans le cas contraire, votre système accumulera de nombreux processus interrompus.