大規模なプロジェクトのさまざまな場所から呼び出すことができるログ モジュールに取り組まなければなりません。私が抱えている問題は、シグナルハンドラー内で実行されるコードからモジュールが呼び出される場合があることです。通常、logging モジュールには localtime() と strftime() を使用して時間データが含まれますが、もちろんこれらの呼び出しは非同期シグナルに対して安全ではなく、シグナル ハンドラー内から呼び出されるとデッドロックが発生する可能性があります。たとえば、処理中にすべてのシグナルハンドラーにフラグを設定させることを除いて、コードが現在シグナルハンドラーコンテキストで実行されているかどうかを確認する方法は (GNU/Linux システム上で) ありますか? シグナル ハンドラーを単純化したほうがよいと思いますが、この場合、ログ モジュールを呼び出す場所を選択することはできません。
3 に答える
最も簡単な方法は、(名前付き)パイプ(PIPE_MAXまでの書き込みはアトミック)またはUDPソケット(idem)を介してログに記録することです。メッセージの発信元は、メッセージを生成する機能で設定できます。もちろん、実際にメッセージを読み取って処理するプロセスが必要ですが、シグナルハンドラーのコンテキスト外に保持することもできます。
ところで:メッセージを受信するために別のプロセスは必要ありません。メッセージを独自のプロセスに送信し、パイプをfd_setに追加(プログラムの読み取り側)することができます(プログラムが選択ループまたはポーリングループにある場合)。または定期的にポーリングします。
まず第一に、あなたの質問 (「私はシグナル ハンドラーにいますか?」) には明確な答えがありません。次のコードを検討してください。
#include <setjmp.h>
#include <signal.h>
jmp_buf jb;
int foo(int s)
{
longjmp(jb,1);
}
int main()
{
if (setjmp(jb)) {
puts("Am I in a signal handler now, or not?");
return 0;
}
signal(SIGINT, foo);
raise(SIGINT);
}
そうは言っても、多くのプログラムにとって意味のある方法でこの質問に答えるために使用できる手法があります。使用する予定のないシグナルを選択し、処理するsa_mask
すべてのシグナルの に追加し、 を使用してシグナル ハンドラをインストールしますsigaction
。次に、 を使用sigprocmask
して現在のシグナル マスクを確認できます。指定したシグナルがシグナル マスク内にある場合は、シグナル ハンドラが呼び出され、まだ返されていないことを意味します (戻ると、元のシグナル マスクが復元されます)。
あなたのシステムは持っていsigpending
ますか?シグナルハンドラー中のその関数の動作がわかりません。ただし、フラグが設定されている場合は、悲観的になり、保留中のシグナルがある場合は async-unsafe 呼び出しをスキップする可能性があります。