2009-08-21 15 views
6

Solaris 10のCでは、プロセス内の任意のスレッドからコールスタックを取得したいと考えています。C内のスレッドからコールスタックを取得

私は多くのワーカースレッドとタイトなループとデッドロックを検出するためにそれらをすべて監視するスレッドを持っています。私が実装したい関数は、監視スレッドが、呼び出しスタックを「ハング」スレッドから数回プリントして、それを終了させることです。

私は、監視スレッドにpstack(system()またはforking)を実行させることでこれを実装する方法を知っています。しかし、私はCでこの関数を実装できるようにしたいと思います。これを行う方法はありますか?

スタックを歩くことで、スレッドがOWN呼び出しスタックを印刷する方法を知っています。これは、アサートにヒットした場合には便利ですが、同じプロセス内の別のスレッドではこれを行う方法ではありません。

ありがとうございました。 NickB

答えて

3

gccを使用している場合は、inbuilt関数__builtin_return_addressを使用できます。 void * __builtin_return_address(符号なしintレベル)

この関数は、関数が呼び出された関数のアドレスを返します。すなわち、機能の呼び出し元。

レベルはレベル数を指定します。 0は現在の関数1が呼び出し元を意味し、2が呼び出し元の呼び出し元を意味します。 次の例では、その使用方法を示します。関数のアドレスを出力することにより、呼び出しスタックを決定することができます。

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

しかし、1つのスレッドが別のスレッドからコールスタックを取得するにはどうすればよいですか? – NickB

4

名前を機能させるアドレスを変換するdladdr()/dladdr1()を使用して、スタックを歩いてwalkcontext()を使用することができます。 walkcontext()はスレッドに対してucontextを取ります。そのスレッドの協力がなければ、スレッドを停止する(例えばPCTWSTOPで)し、そのスレッドのlwpstatus構造体のpr_oldcontextフィールドからアドレスを読み取って、/proc/self/lstatusから取得して、そのスレッドのUコンテキストを取得できます。

関連する問題