のLinuxでboost::interprocess::shared_memory_object
を使用してIPCを実行しています(匿名ミューテックスの例)。boost :: interprocess :: scoped_lockを保持している間スリープすると、決して解放されません。
shared_memory_object
を作成して書き込みを行うサーバプロセスがあり、interprocess_mutex
をscoped_lock
にラップしています。もう一方が書いたものを印刷するクライアントプロセス - この場合、それはint
です。
私は問題に遭遇しました。サーバがミューテックスを保持している間スリープした場合、クライアントプロセスは決してそれを取得できず、永遠に待ちます。
バギーサーバーループ:
using namespace boost::interprocess;
int n = 0;
while (1) {
std::cerr << "acquiring mutex... ";
{
// "data" is a struct on the shared mem. and contains a mutex and an int
scoped_lock<interprocess_mutex> lock(data->mutex);
data->a = n++;
std::cerr << n << std::endl;
sleep(1);
} // if this bracket is placed before "sleep", everything works
}
サーバー出力:
acquiring mutex... 1
acquiring mutex... 2
acquiring mutex... 3
acquiring mutex... 4
クライアントループ:
while(1) {
std::cerr << "acquiring mutex... ";
{
scoped_lock<interprocess_mutex> lock(data->mutex);
std::cerr << data->a << std::endl;
}
sleep(1);
}
クライアント出力は(永遠に待つ):
acquiring mutex...
事は、私がsleep
呼び出しの前の行にブラケットを移動した場合、すべてが動作します、です。どうして?ロックされたミューテックスでスリープ状態になると、ミューテックスが永久にロックされるとは思わなかった。
カーネルがサーバプロセスを起動すると、スコープは終了し、mutexは解放されますが、待機プロセスには実行の機会は与えられません。その後、サーバーはロックを再度取得します...しかし、それは意味をなさないと思われます。
ありがとうございます!
ブーストはスレッドをあきらめて(Linuxのschedu_yieldのように)呼び出すことができます:boost :: this_thread :: yield() – teeks99
ありがとう。 'sleep(0)'はうまく動作し、その理論を確認します。私はミューテックスをリリースするという行為は少なくともシステムコールとそれに伴う再スケジューリングを引き起こすという印象を受けましたが、私は間違っていました。 –