ソケットやデータベース接続などを使用するプロセスがあります。これは基本的に、センサーデータとWebインターフェイスの間を中継するサーバープロセスであるため、アプリケーションが強制終了された場合に正常に終了するようにすることが重要です。
セグメンテーション違反(少なくともデバッグ用)やkillシグナルなどの予期しない例外を処理して、接続を閉じ、実行中のスレッドを停止して、プロセスが使用しているものを混乱させないようにするにはどうすればよいですか?
シグナルハンドラーをインストールしてシグナルをキャッチしますが、99%の場合、終了してLinux OSにクリーンアップを任せたいだけです。これにより、すべてのファイル、ソケット、空きメモリ、シャットダウンスレッドが正常に閉じられます。
したがって、ソケットでメッセージを送信するなど、特に実行したいことがない限り、プロセスを終了して、シグナルをキャッチしようとしないでください。
信号をキャッチするのは難しいです。あなたは注意する必要があります。最初のステップは、sigaction
を使用して、目的の信号の信号ハンドラーをインストールすることです。
応答するシグナルのセットを選択し、それらがプロセスにとって何を意味するかを選択します。たとえば、SIGTERM
が終了し、SIGHUP
が再起動し、SIGUSR1
設定などをリロードします。
すべてのシグナルに応答しようとしないでください。また、プログラムのエラーを示すシグナルの後に「クリーンアップ」しようとしないでください。 SIGKILL
をキャッチできません。 SIGSEGV
、SIGBUS
、およびそれらのような他のものは、非常に正当な理由がない限り、捕まえられるべきではありません。デバッグする場合は、コアダンプの上限を引き上げます。デバッガーをコアイメージにアタッチすることは、あなたや私がこれまでにコーディングしたものよりもはるかに効果的です。 (SIGSEGV
などの後でクリーンアップしようとすると、クリーンアップコードによって追加のSIGSEGV
が発生し、状況がすぐに悪化する可能性があることに注意してください。混乱を避けて、 SIGSEGV
プログラムを終了します。)
信号の処理方法には注意が必要です。アプリケーションにメインループ(例:select
またはpoll
)がある場合、シグナルハンドラーはフラグを設定するか、特別なパイプにバイトを書き込んで、メインループを終了するように通知できます。 siglongjmp
を使用してシグナルハンドラーからジャンプすることもできますが、これを正しく行うのは非常に難しく、通常は必要なものではありません。
アプリケーションがどのように構成され、何をするのかを知らずに何かを推奨するのは難しいです。
また、シグナルハンドラ自体はほとんど何もしないはずです。多くの関数は、シグナルハンドラーから呼び出すのは安全ではありません。
私は時々SIGSEGVのバックトレースを取得したいのですが、キャッチ部分は次のようになります。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sig_handler(int);
int main() {
signal(SIGSEGV, sig_handler);
int *p = NULL;
return *p;
}
void sig_handler(int sig) {
switch (sig) {
case SIGSEGV:
fprintf(stderr, "give out a backtrace or something...\n");
abort();
default:
fprintf(stderr, "wasn't expecting that!\n");
abort();
}
}
あなたはこれらのものを非常に注意深く扱うことを望みます、例えば。別の信号をトリガーできないことを確認してください。