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.