2009-08-21 10 views
6

En C en Solaris 10, me gustaría obtener la pila de llamadas de un subproceso arbitrario dentro de un proceso.Obtener pila de llamadas desde cualquier subproceso dentro de C

Tengo muchos subprocesos de trabajo y un subproceso que los supervisa a todos para detectar bucles estrechos y bloqueos. La función que me gustaría implementar es que el subproceso de supervisión imprima varias veces la pila de llamadas del subproceso "bloqueado" antes de que lo mate.

Sé cómo implementar esto haciendo que el subproceso de supervisión ejecute pstack (con sistema() o mediante bifurcación). Pero me gustaría poder implementar esta función en C. ¿Hay alguna manera de hacer esto?

Sé cómo hacer que un hilo imprima su PROPIA pila de llamadas, recorriendo la pila, lo cual es útil si golpea una afirmación, pero no cómo hacer esto para otra secuencia dentro del mismo proceso.

Gracias por cualquier ayuda. NickB

Respuesta

3

Si está utilizando gcc puede usar la función incorporada __builtin_return_address. void * __builtin_return_address (sin signo int level)

la función devuelve la dirección de la función de la que se llama a la función. es decir, el que llama de la función.

El nivel especifica cuántos niveles. 0 significa que la función actual 1 significa que llama, 2 significa que llama a quien llama. El siguiente ejemplo proporcionará el uso. Al imprimir las direcciones de la función, se puede determinar la pila de llamadas.

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

Pero, ¿cómo permite eso que un hilo obtenga la pila de llamadas de otro hilo? – NickB

4

Puede utilizar walkcontext() a caminar por la pila, utilizando dladdr()/dladdr1() para convertir las direcciones de funcionar nombres. walkcontext() toma un ucontext para el hilo. Si no tiene la cooperación de ese hilo, puede obtener un ucontext deteniendo el hilo (por ejemplo, con PCTWSTOP) y luego leyendo su dirección del campo pr_oldcontext de la estructura lwpstatus para ese hilo, obtenido de /proc/self/lstatus.

Cuestiones relacionadas