2009-08-21 10 views
6

W języku C na Solarisie 10, chciałbym uzyskać stos wywołań z dowolnego wątku w procesie.Uzyskaj stos wywołań z dowolnego wątku w C

Mam wiele wątków roboczych i jeden wątek, który monitoruje je wszystkie w celu wykrycia ciasnych pętli i zakleszczeń. Funkcja, którą chciałbym zaimplementować, służy do monitorowania wątku, aby kilka razy wydrukować stos wywołań z wątku "zawieszonego", zanim go zabije.

Wiem, jak to wdrożyć, mając wątek monitorowania wykonać pstack (z system() lub przez rozwidlenie). Ale chciałbym móc wdrożyć tę funkcję w C. Czy jest jakiś sposób to zrobić?

Wiem, jak sprawić, aby wątek wydrukował swój stos wywoławczy WŁASNEGO, chodząc po stosie, co jest przydatne, gdy trafi w potwierdzenie, ale nie w jaki sposób zrobić to dla innego wątku w ramach tego samego procesu.

Dzięki za pomoc. NickB

Odpowiedz

3

Jeśli używasz gcc, możesz użyć wbudowanej funkcji __builtin_return_address. void * __builtin_return_address (unsigned int level)

Funkcja zwraca adres funkcji, z której wywoływana jest funkcja. to jest wywołujący funkcję.

Poziom określa liczbę poziomów. 0 oznacza aktualną funkcję 1 oznacza dzwoniącego, 2 oznacza dzwoniącego dzwoniącego. Poniższy przykład przedstawia sposób użycia. Drukując adresy funkcji, można określić stos wywołań.

int calla() 
{ 
    printf("Inside calla\n"); 
    printf("A1=%x\n",__builtin_return_address (0)); 
    printf("A2=%x\n",__builtin_return_address (1)); 
    printf("A3=%x\n",__builtin_return_address (2)); 
} 
int callb() 
{ 
    printf("Inside callb\n"); 
    calle(); 
    printf("B1=%x\n",__builtin_return_address (0)); 
    printf("B2=%x\n",__builtin_return_address (1)); 
    printf("B3=%x\n",__builtin_return_address (2)); 
} 
int callc() 
{ 
    printf("Inside callc\n"); 
    printf("C1=%x\n",__builtin_return_address (0)); 
    printf("C2=%x\n",__builtin_return_address (1)); 
    printf("C3=%x\n",__builtin_return_address (2)); 
} 
int calld() 
{ 
    printf("Inside calld\n"); 
    printf("D1=%x\n",__builtin_return_address (0)); 
    printf("D2=%x\n",__builtin_return_address (1)); 
    printf("D3=%x\n",__builtin_return_address (2)); 
} 
int calle() 
{ 
    printf("Inside calle\n"); 
    printf("E1=%x\n",__builtin_return_address (0)); 
    printf("E2=%x\n",__builtin_return_address (1)); 
    printf("E3=%x\n",__builtin_return_address (2)); 
} 
main() 
{ 
    printf("Address of main=%x calla=%x callb=%x callc=%x calld=%x calle=%x\n",main,calla,callb,callc,calld,calle); 
    calla(); 
    callb(); 
    calld(); 
} 
+0

Ale w jaki sposób pozwala to jednemu wątkowi uzyskać stos wywołań z innego wątku? – NickB

4

Można użyć walkcontext() chodzić stos, używając dladdr()/dladdr1() do konwersji adresów funkcjonować nazwy. walkcontext() ma ucontext dla wątku. Jeśli nie masz współpracy z tym wątkiem, możesz uzyskać dla niego tekst ucontext, zatrzymując wątek (np. Z PCTWSTOP), a następnie odczytując jego adres z pola pr_oldcontext struktury lwpstatus dla tego wątku, uzyskanej z /proc/self/lstatus.