私は多数の信号を処理するツールを開発しています。その他記号)とsigaction()
。
新しい信号が入っていて古い信号が信号ハンドラの内部にある場合は、この状況を処理する必要があります。したがって、次の「スタック」を処理できる必要があります。
- 通常のコース
- マネージャーシグナル1
- マネージャーシグナル2
- ...そしておそらくより多くの信号ハンドラがあります...
(私が知っている限り、シグナルハンドラは独自のコンテキストで実行されるため、実際のスタックはありませんが、これが私の問題を説明する方法です。)
glibc2 APIを使用しています。
問題は絶望的ではありません(メインの実行フローで後で処理されるように、基本プロセスの再入データ構造に信号情報を渡すことができます)。ハンドラが「スタック」の最初のハンドラであることを確認する信頼できる方法が必要です。
信号をマスクすることはオプションではなく、(結合された信号で)信号損失を最小限に抑えることが優先されます。
しなければならない信頼できる方法。グローバルsigatomic_tをスピンロックとして使用することも問題になります。起動後すぐに新しい信号が表示されないことを保証できないためです。シグナル1ハンドラ(ロックを取得しようとする前)
マニュアルとglibc文書を掘り下げた後、シグナルハンドラが最初のハンドラであることを確認するための信頼できる方法が見つかりませんでした。これは可能ですか?
ベストアンサー1
シグナルをブロックするようにシグナルハンドラを設定してから、このシグナルを受信したとコメントしてブロックを解除します。
volatile_t sig_atomic_t signal_count;
void mysignalhandler(int signo) {
sig_atomic_t depth = ++signal_count;
pending_signals.push(signo)
if (depth > 1) return;
sigprocmask(<unblock all signals>)
while (!pending_signals.empty())
/* Process pending_signals */
}
最後の保留中の_signals.empty()チェックとiretの間に小さな競争条件があることに注意してください。メインコードでいくつかのチェックを行う場合は、そのままにしておきます。現在持っている信号の量を考えると、とにかく早く処理されます。それ以外の場合は、最後に信号時間を再測定して戻す前に、保留中の信号がまだ空であることを確認できます。