プロセスが共有メモリにミューテックスを作成してロックし、ミューテックスがロックされている間にコアをダンプするとします。
別のプロセスで、ミューテックスがすでにロックされているがどのプロセスにも所有されていないことを検出するにはどうすればよいですか?
プロセスが共有メモリにミューテックスを作成してロックし、ミューテックスがロックされている間にコアをダンプするとします。
別のプロセスで、ミューテックスがすでにロックされているがどのプロセスにも所有されていないことを検出するにはどうすればよいですか?
正確な答えは、堅牢なミューテックスの形で提供されているようです。
POSIX によれば、pthread_mutexattr_setrobust() を使用して、pthread ミューテックスを「堅牢」に初期化できます。ミューテックスを保持しているプロセスが終了すると、次に取得するスレッドは EOWNERDEAD を受け取り (ただし、ミューテックスの取得は成功します)、クリーンアップを実行する必要があることを認識します。次に、pthread_mutex_consistent() を使用して、取得したミューテックスが再び整合性を保っていることを通知する必要があります。
これを機能させるには、明らかにカーネルと libc の両方のサポートが必要です。Linux では、この背後にあるカーネル サポートは「堅牢な futex」と呼ばれ、glibc HEAD に適用されているユーザー空間の更新への参照を見つけました。
実際には、少なくとも Linux の世界では、これに対するサポートはまだフィルターにかけられていないようです。これらの関数が利用できない場合は、代わりに pthread_mutexattr_setrobust_np() が見つかる可能性があります。これは、私が収集できる限り、同じセマンティクスを提供する非 POSIX の前任者のようです。Solaris のドキュメントと Debian の /usr/include/pthread.h の両方で pthread_mutexattr_setrobust_np() への参照を見つけました。
POSIX 仕様は、http ://www.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html にあります。
Linux などで作業している場合は、(私が想定している) pthreads ミューテックスの代わりに名前付きセマフォを使用することを検討してください。独自の登録テーブルを作成して共有メモリに配置する以外に、pthreads ミューテックスのロック PID を特定する方法はないと思います。
ファイルベースのロック (を使用flock(2)
) はどうですか? これらは、それを保持しているプロセスが終了すると自動的に解放されます。
デモプログラム:
#include <stdio.h>
#include <time.h>
#include <sys/file.h>
void main() {
FILE * f = fopen("testfile", "w+");
printf("pid=%u time=%u Getting lock\n", getpid(), time(NULL));
flock(fileno(f), LOCK_EX);
printf("pid=%u time=%u Got lock\n", getpid(), time(NULL));
sleep(5);
printf("pid=%u time=%u Crashing\n", getpid(), time(NULL));
*(int *)NULL = 1;
}
出力 (わかりやすくするために、PID と時間を少し切り捨てました):
$ ./a.out & sleep 2 ; ./a.out
[1] 15
pid=15 time=137 Getting lock
pid=15 time=137 Got lock
pid=17 time=139 Getting lock
pid=15 time=142 Crashing
pid=17 time=142 Got lock
pid=17 time=147 Crashing
[1]+ Segmentation fault ./a.out
Segmentation fault
最初のプログラムがロックを取得し、5 秒間スリープし始めます。2 秒後、プログラムの 2 番目のインスタンスが開始され、ロックを取得しようとしてブロックされます。3 秒後、最初のプログラムが segfault を起こし (bash は後ほど通知しません)、すぐに 2 番目のプログラムがロックを取得して続行します。
誰かが同じ考えを持ち、使用に関するこの議論を見つける場合にのみ、私はこの間違った投稿を削除せずに残しました!
このアプローチを使用できます。1) POSIX 共有ミューテックスをロックします。2) プロセス ID を共有メモリに保存します。3) 共有ミューテックスのロックを解除する 4) 正しい終了時にプロセス ID を消去する
プロセスがコアダンプした場合、次のプロセスは共有メモリにステップ #2 で保存されたプロセス ID があることを検出します。OS にこのプロセス ID を持つプロセスが存在しない場合、誰も共有ミューテックスを所有していません。したがって、プロセス ID を置き換えるだけで済みます。
コメントに答えるために更新します。
シナリオ 1: 1. P1 が開始する 2. 名前付きミューテックスが存在しない場合、P1 が名前付きミューテックスを作成/開く 3. P1 が名前付きミューテックスを timed_lock し、正常にロックする (必要に応じて 10 秒間待機する); 4. P1 コアダンプ 5. P2 はコアダンプ後に開始します 6. P2 は名前付きミューテックスを作成/開きます。存在し、問題ありません 7. P2 は名前付きミューテックスを timed_lock し、ロックに失敗します (必要に応じて 10 秒間待機します)。8. P2 は名前付きミューテックスを削除します 9. P2 は名前付きミューテックスを再作成してロックします
オペレーティング システムが提供するセマフォを使用する必要があります。
オペレーティング システムは、プロセスが終了するか正常に終了するかに関係なく、プロセスが開いているすべてのリソースを解放します。