Handbuch zur dynamischen Ablaufverfolgung in Solaris

Die Aktion ustack()

Die Ablaufverfolgung des Stacks eines Prozess-Threads zum Zeitpunkt der Aktivierung eines bestimmten Prüfpunkts gibt häufig sehr gründlich Aufschluss über ein Problem. Die Aktion ustack() dient zur Ablaufverfolgung des Stacks eines Benutzer-Threads. Wenn beispielsweise ein Prozess, der zahlreiche Dateien öffnet, gelegentlich beim open(2)-Systemaufruf scheitert, können Sie mit der Aktion ustack() den Codepfad ermitteln, der den fehlgeschlagenen open() ausführt:

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();
}

Dieses Skript veranschaulicht auch die Verwendung der Makrovariable $1, die den Wert des ersten in der dtrace(1M)-Befehlszeile angegebenen Operanden annimmt:


# 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

Die Aktion ustack() zeichnet Programmzählerwerte (PC) für den Stack auf und dtrace(1M) löst diese PC-Werte anhand der Symboltabellen des Prozesses in Symbolnamen auf. Kann dtrace einen PC-Wert nicht in ein Symbol auflösen, wird der Wert als Hexadezimalzahl ausgegeben.

Wenn ein Prozess bereits vor der Formatierung der ustack()-Daten für die Ausgabe vorhanden ist oder mit kill abgebrochen wird, kann dtrace die PC-Werte im Stack-Protokoll unter Umständen nicht in Symbolnamen umwandeln und ist gezwungen, sie als Hexadezimalzahlen anzuzeigen. Um diese Einschränkung zu umgehen, übergeben Sie -dtrace mit der Option -c oder p gezielt einen Prozess. Ausführliche Informationen zu diesen und anderen Optionen finden Sie in Kapitel 14Das Dienstprogramm dtrace(1M). Sind Prozess-ID oder Befehl im Voraus nicht bekannt, lässt sich die Einschränkung auch mit folgendem D-Programm umgehen:

/*
 * 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;
}

Das obige Skript hält einen Prozess kurz vor dessen Beendigung an, wenn die Aktion ustack() auf einen Thread in diesem Prozess angewendet wurde. Diese Technik gewährleistet, dass der Befehl dtrace in der Lage ist, die PC-Werte in symbolische Namen aufzulösen. Beachten Sie, dass der Wert von stop_pids[pid], nachdem er zum Löschen der dynamischen Variable benutzt wurde, 0 beträgt. Denken Sie daran, angehaltene Prozesse mit dem Befehl prun(1) wieder zum Laufen zu bringen. Anderenfalls sammeln sich auf dem System zahlreiche angehaltene Prozesse an.