Rastrear uma pilha do segmento do processo na hora em que um teste específico é ativado é freqüentemente útil para examinar um problema em maiores detalhes. A ação ustack() rastreia a pilha do segmento do usuário. Se, por exemplo, um processo que abre muitos arquivos falhar ocasionalmente na chamada do sistema open(2), use a ação ustack() para descobrir o caminho do código que executa a função open() falha:
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(); }
Este script também ilustra o uso da variável de macro $1 que usa o valor do primeiro operando especificado na linha de comando do 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 |
A ação ustack() registra os valores do contador do programa ( PC) da pilha e o dtrace(1M) resolve esses valores de PC para nomes de símbolo, procurando nas tabelas de símbolos do processo. Se o dtrace não puder resolver o valor de PC para um símbolo, ele imprimirá o valor como um inteiro hexadecimal.
Se um processo sair ou for interrompido antes de os dados de ustack() serem formatados para saída, o dtrace talvez não consiga converter os valores de PC no rastreamento da pilha para nomes de símbolo, e será forçado a exibi-los como inteiros hexadecimais. Para resolver esta limitação, especifique um processo de interesse com a opção -c ou -p para dtrace. Consulte o Capítulo 14Utilitário dtrace(1M) para obter detalhes sobre estas e outras opções. Se o ID do processo ou o comando não for conhecido com antecedência, o exemplo seguinte de programa em D poderá ser usado para resolver a limitação:
/* * 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; }
O script acima irá parar um processo antes que ele saia, se a ação ustack() tiver sido aplicada a um segmento nesse processo. Esta técnica garante que o comando dtrace será capaz de resolver os valores de PC para nomes simbólicos. Observe que o valor de stop_pids[pid] é definido como 0 depois que ele tiver sido usado para limpar a variável dinâmica. Lembre-se de definir os processos interrompidos que estão sendo executados novamente usando o comando prun(1) ou o seu sistema acumulará muitos processos interrompidos.