私はLinux上で同時に実行できる何回の同時実行を制御するラッパーを作成しようとしています。これを行うために、私はシステム全体のカウントセマフォを使用しています。セマフォを作成してsem_wait()
を実行し、子プロセスを起動して、子プロセスが終了するとsem_post()
を実行します。それは結構です。sem_wait()/ sem_post()のシグナル安全な使用
問題は、このラッパーに送信されたシグナルを安全に処理する方法です。シグナルをキャッチしない場合、コマンドはsem_post()
を実行せずに終了し、セマフォーカウントが1だけ永久に減少します。そこで、sem_post()
を実行するシグナルハンドラを作成しました。しかし、まだ、問題があります。
ハンドラがsem_wait()
が実行される前に、信号はsem_wait()
なしで発生するsem_post()
を引き起こし、sem_wait()
完了する前に到着する可能性が取り付けられている場合。シグナルハンドラを設定する前にsem_wait()
を実行すると、その逆が可能です。
明らかに次のステップは、ハンドラとsem_wait()
の設定中に信号をブロックすることでした。これは私が今持っているものの擬似コードです:
void handler(int sig)
{
sem_post(sem);
exit(1);
}
...
sigprocmask(...); /* Block signals */
sigaction(...); /* Set signal handler */
sem_wait(sem);
sigprocmask(...); /* Unblock signals */
RunChild();
sem_post(sem);
exit(0);
問題は今sem_wait()
をブロックすることができますし、その時に、信号がブロックされているということです。プロセスを強制終了しようとするユーザーは、 "kill -9"に頼ることになるかもしれません。これは、何があってもそのケースを処理できないため、私が励ましたくない動作です。 sem_trywait()
を短時間使用し、sigpending()
をテストすることができましたが、セマフォを待っているプロセスが次に実行される保証がなくなるため、公平性に影響します。
セマフォーの取得中に信号を処理できる本当に安全なソリューションはありますか?私は "セマフォーを持っていますか?"というメッセージに頼ってシグナルブロッキングを取り除くことを検討していますが、これはセマフォーを取得してからグローバルに設定するのが100%安全ではありません。
私が不明な場合は申し訳ありません。sem_wait()はあなたが言うようにシグナルをブロックさせませんが、ブロックするためにsigprocmask()を使用しています。しかし、私はあなたが正しい解決策を持っていると思います。これは、ハンドラが終了せず、 "終了する時間"と言うフラグを設定すべきであることを意味するEINTRエラーコードを調べることです。私はそれをテストします。ありがとう。 – Jeremy
それはうまくいった。私はシグナルのブロックを取り除き、シグナルハンドラーをグローバルな意味を設定するように変更しました。 sem_wait()がエラーを返した場合は、終了してセマフォカウントを保持します。私が子供を待っているなら、私はtimeToQuitをグローバルにテストします。終了する時が来たら、私は子供を殺し、セマフォカウントを保持するsem_post()を行います。ありがとう。それはkill -9を無視してシグナル安全でなければなりません。 – Jeremy