2012-04-11 11 views
1

できるだけ多くの終了原因イベントを処理する理由について、ログを取ったり、処理したり、何か手がかりを残す方法はありますか?Linux上でC++でプロセス終了の理由をログに記録する

私のアプリケーション用のログツールがあり、毎分多くのメッセージがログに記録されます。私はすべてのプログラムをスーパーのtry-catchブロックで実行しているので、未処理の例外をすべて記録できます。私は最近、プロセスを終了させる可能性のあるさまざまなプロセスシグナルのハンドラを登録しようとしました。しかし、アプリケーションは1日に数回もクラッシュしていますが、理由はわかりません。

他にもいくつの致命的なイベントがログに記録されたり処理されなかったりする可能性がありますか?私がまだ気付いていないいくつかの新しいタイプのイベントでプロセスが死んだとき、暗闇の中に一貫して残されているよりむしろ、これを行う正しい方法があると思います。

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

+1

余分なスレッド、スレッドされたサブシステム、アウトプロセスサーバーはありますか? 「スーパーのtry-catchブロック」は、このような環境で発生したエラーをトラップしません。 –

+0

はい複数のスレッドがあります。私は今それらのそれぞれのtry-catchブロックを追加しました。私は「プロセス外のサーバー」が何であるか知りません。私は間違っている可能性がありますWindowsのもののように見える速いGoogleから、? – Pryo

答えて

2

あなたは、予期しない例外を処理する機能を登録することができます。

set_unexpected()

とDELTませんが)terminatを(呼び出すためのアプリケーションの原因となります。

あなたは、終了時に物事をログに記録する機能を登録することができます。

set_terminate()

出口が異常発生した場合は、それだけのものをとするようなものは(フラグを設定行います独自のatexit()ロギング機能を追加することができますmainを出る直前にフラグをセットする)。

シグナルハンドラは、(あなたがそれらを移植できるようにしたい場合は特に)、注意が必要です。あなたがそれらを使用する場合は、あなたがそう内部で安全に行うことができるものに限定されている、彼らは通常のコードで扱うことができるように、私は通常、グローバルフラグを設定することに自分自身を制限する(もちろん、あなたが終了しているならば、それは非常に制限されます)。これはのみSIGINT/SIGTERMシグナルの世話をする、当然の

#include <iostream> 
#include <signal.h> 

sigint_handler(int s) { 
    std::cout<<"signal caught: "<<s<<std::endl; 
    ::exit(-1); 
} 

void setup_signal() { 
    struct sigaction sigIntHandler; 
    sigIntHandler.sa_handler = sigint_handler; 
    sigemptyset(&sigIntHandler.sa_mask); 
    sigIntHandler.sa_flags = 0; 
    sigaction(SIGINT, &sigIntHandler, NULL); 
    sigaction(SIGTERM, &sigIntHandler, NULL); 
} 

int main() { 
    setup_signal(); 
    /* do stuff */ 
    return 0; 
} 

2

スーパーブロックを持つブロックとは、キャッチ可能な例外が未処理であることを意味します。これらのブロックは、すべての開始スレッドに対して必要になります。

これ以外にも、signalを使用して終了信号を捕捉できます。これらは次のとおりです。

  • SIGABRT(シグナルアボート)アボート機能によって開始されるなどの異常終了。
  • SIGFPE(信号浮動小数点例外)ゼロ除算やオーバフローを引き起こす演算(必ずしも浮動小数点演算ではない)などの誤った算術演算。
  • SIGILL(信号不正命令)不正な命令など、無効な機能イメージです。これは、一般に、コードが破損しているか、データを実行しようとしていることが原因です。
  • SIGINT(信号割り込み)インタラクティブな注意信号。一般に、アプリケーションユーザーによって生成されます。
  • SIGSEGV(シグナルセグメンテーション違反)ストレージへの無効なアクセス:プログラムがメモリ外での読み取りまたは書き込みを試みると、メモリに割り当てられます。 SIGTERM(信号終端)プログラムに送信された終端要求。
  • シグナルが実装によって定義されていますが、ほとんどのクラッシュ原因はこれらによってカバーされる必要があります。
また

、それはプログラムがクラッシュが、主な(しかし、私はあなたが既にカバーされていることがあると思い)またはexitへの呼び出しを経由してから戻るのいずれかによって終了していないことをすることができます。この場合、プログラムの戻り値を確認してログに記録することができます。

+0

+1は、すべてのスレッドに対してtry/catchブロックが必要であることを指摘しています。私はそれを逃した。 – Pryo

0

1のコードは、価値が多くの言葉です。あなたはまた、すべてのatexitで、このコードを更新する必要があります()、呼び出したset_terminate、スーパーのtry/catchなど。あなたは見つけることができます。そして、あなたは、セグメンテーション違反/バスエラー/何でも...よく、あなたは運命だ:)

+0

間違いなくそれをしないでください。シグナルハンドラでファイルに書き込むのと同じくらい複雑な作業を行うべきではありません。フラグを設定し、ataxit()登録関数の状況を処理します。 –

+0

あなたは正しいですが、atexit()はkill/termシグナルを処理しますか?もちろん、私はあなたに同意、1の代わりに、彼は標準出力/標準エラー出力を使用する必要があり、それらのcirconstancesでファイルに書き込むと、親プロセスのファイルにそれをリダイレクトするべきではありません。 – zmo

0

をに実行する場合には、この質問をチェックしてください。そこ How to find the reason for a dead process without log file on unix?

あなたは、プロセスの終了コードを取得するにはbashを使用すると、シグナルハンドラまたは終了コールバックのいずれかの種類を使用するよりも簡単にくらいであることがわかります。

2

私のプログラムで使用しているのは、私のために働く....私のプログラムがクラッシュすると、クラッシュサイトのスタックトレースがstdoutに出力されます(おそらく、ファイルなどにリダイレクトされます後で)。あなたは、スタックトレースは、人間が読み取り可能な関数名が含まれていることを確認するCXXFLAGSにフラグとして-rdynamic渡す必要があり、および/またはあなたのMakefileのLFLAGSも

注意。

#include <stdio.h> 
#include <signal.h> 
#include <execinfo.h> 

void PrintStackTrace() 
{ 
    void *array[256]; 
    size_t size = backtrace(array, 256); 
    char ** strings = backtrace_symbols(array, 256); 
    if (strings) 
    { 
     printf("--Stack trace follows (%zd frames):\n", size); 
     for (size_t i = 0; i < size; i++) printf(" %s\n", strings[i]); 
     printf("--End Stack trace\n"); 
     free(strings); 
    } 
    else printf("PrintStackTrace: Error, could not generate stack trace!\n"); 
} 

static void CrashSignalHandler(int sig) 
{ 
    // Uninstall this handler, to avoid the possibility of an infinite regress 
    signal(SIGSEGV, SIG_DFL); 
    signal(SIGBUS, SIG_DFL); 
    signal(SIGILL, SIG_DFL); 
    signal(SIGABRT, SIG_DFL); 
    signal(SIGFPE, SIG_DFL); 

    printf("CrashSignalHandler called with signal %i... I'm going to print a stack trace, then kill the process.\n", sig); 
    PrintStackTrace(); 
    printf("Crashed process aborting now.... bye!\n"); 
    fflush(stdout); 
    abort(); 
} 

int main(int argc, char ** argv) 
{ 
    signal(SIGSEGV, CrashSignalHandler); 
    signal(SIGBUS, CrashSignalHandler); 
    signal(SIGILL, CrashSignalHandler); 
    signal(SIGABRT, CrashSignalHandler); 
    signal(SIGFPE, CrashSignalHandler); 

    [...remainder of your program goes here...] 
} 
関連する問題