2009-08-21 20 views
6

In C su Solaris 10, mi piacerebbe ottenere lo stack di chiamata da un thread arbitrario all'interno di un processo.Ottenere lo stack di chiamate da qualsiasi thread all'interno di C

Ho molti thread di lavoro e un thread che li monitora tutti per rilevare loop stretti e deadlock. La funzione che vorrei implementare è che il thread di monitoraggio stampi più volte lo stack di chiamate dal thread "sospeso" prima che lo uccida.

So come implementarlo facendo in modo che il thread di monitoraggio esegua pstack (con system() o forking). Ma mi piacerebbe essere in grado di implementare questa funzione in C. C'è un modo per farlo?

So come far stampare a un thread lo stack di chiamata OWN, camminando nello stack, che è utile se raggiunge un assert, ma non come farlo per un altro thread all'interno dello stesso processo.

Grazie per qualsiasi aiuto. NickB

risposta

3

Se si utilizza gcc, è possibile utilizzare la funzione incorporata __builtin_return_address. void * __builtin_return_address (livello int unsigned)

La funzione restituisce l'indirizzo della funzione da cui viene richiamata la funzione. io il chiamante della funzione.

Il livello specifica quanti livelli. 0 indica che la funzione corrente 1 indica il chiamante, 2 indica il chiamante del chiamante. L'esempio seguente fornirà l'utilizzo. Stampando gli indirizzi della funzione, è possibile determinare lo stack delle chiamate.

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

Ma in che modo ciò consente a un thread di ottenere lo stack di chiamate da un altro thread? – NickB

4

È possibile utilizzare walkcontext() a camminare lo stack, utilizzando dladdr()/dladdr1() per convertire gli indirizzi di funzionare nomi. walkcontext() prende uno ucontext per il thread. Se non si dispone della collaborazione di tale thread, è possibile ottenerne un ucontext arrestando il thread (ad esempio con PCTWSTOP) e quindi leggendo il relativo indirizzo dal campo pr_oldcontext della struttura lwpstatus per quel thread, ottenuto da /proc/self/lstatus.

Problemi correlati