2011-04-06 17 views
0

GMutexの問題をデバッグするために書いたテストプログラムがありますが、それはわかりません。私はスコープ内でmutexをロックしたりアンロックするために、以下のクラスを使用しています。これはBOOSTのガードに似ています。 apRegistryLockは*型GMutexのメンバ変数であり、私が今までRegisterSessionを呼び出す前に()g_mutex_new使用して初期化されGMutexを2回ロックすることは可能ですか?

bool van::cSessionManager::RegisterSession(const std::string &iSessionId) 
{ 
cSessionMutex lRegistryLock (apRegistryLock); 

// SOME CODE 
} 

を次のように

/// @brief Helper class used to create a mutex. 
    /// 
    /// This helper Mutex class will lock a mutex upon creation and unlock when deleted. 
    /// This class may also be referred to as a guard. 
    /// 
    /// Therefore this class allows scoped access to the Mutex's locking and unlocking operations 
    /// and is good practice since it ensures that a Mutex is unlocked, even if an exception is thrown. 
    /// 
    class cSessionMutex 
    { 
     GMutex* apMutex; 
     /// The object used for logging. 
     mutable cLog aLog; 

    public: 
     cSessionMutex (GMutex *ipMutex) : apMutex(ipMutex), aLog ("LOG", "->") 
     { 
     g_mutex_lock(apMutex); 
     aLog << cLog::msDebug << "MUTEX LOCK " << apMutex << "," << this << cLog::msEndL; 
     } 

     ~cSessionMutex() 
     { 
     aLog << cLog::msDebug << "MUTEX UNLOCK " << apMutex << "," << this << cLog::msEndL; 
     g_mutex_unlock(apMutex); 
     } 
    }; 

このクラスを使用して、私はそれを呼び出します。これにより

はRegisterSessionが(上記のコンストラクタから)ログ

[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14ad7ae10 
[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14af7ce10 

であることを最初の数回のために呼び出されたとき、私はいくつかのスレッドでアプリケーションを実行すると、私は時々最初に気づく、と述べました同じミューテックスで異なるインスタンスを持つ行に2回記録されます。したがって、mutexが2回ロックされているか、2番目のロックが無視されていることを示唆しています。これは深刻な問題です。

さらに、これらのログがg_thread_self()関数を使用して同じスレッドから開始されたかどうかを確認することも確認してください。したがって、ミューテックスが別々のスレッドから2回ロックされたことを示唆しています。

私の質問は、これがどのように起こるかです。

+0

以下の回答は部分的に正しいことに注意してください。それは本当に実装に依存しているので、すべてのケースで正しいわけではありません。 Ubuntuおよび/またはLinux RHでPOSIXスレッドを実行しているシステムでは、同じスレッド内の2番目のロックは無視されず、実際にはロックされ、デッドロックによって拡張されます(これを確認するテストが作成されます)。しかし、上記の場合、これを初めて実行するときはこれを実行しません。私はテストアプリケーションでvalgrind --tool = drdと--tool = helcheckを実行しようとしましたが、基本的に私が見ていることを確認しました:2番目のロックは無視されるようです。 – bbazso

+0

これは、バッファリングのために再注文されたログメッセージだけではないのですか? – Spudd86

+0

私はそれがロギングかもしれないと思ったので、ロックされている間にアクセスが行われ、このアサートが実際にトリガーされた場合でも、コード内にアサーションがあります。だから、これは本当にmutexロックに問題があり、私がそれをテストしているのではないことを示唆しているようです。 – bbazso

答えて

0

私のケースでは、同じmutexでg_cond_timed_wait関数を呼び出していたが、mutexがロックされていない別のスレッドがあった。この場合、g_cond_timed_wait関数はロックされていないミューテックスをロック解除し、ミューテックスを未定義の状態にします。これは、なぜこの問題で説明されている動作を見ているのかを説明します。

2

同じスレッドの同じコールチェーンで2回呼び出された場合、これが起こる可能性があります。 2番目のロックは通常(常にではありませんが)無視されます。少なくともpthreadでは、複数のロックを数えて設定することが可能です。

+0

mutexのいくつかの実装では、同じスレッドがmutexを2回ロックすることができます。それに対応して2回ロックを解除する必要があります。 –

+0

これは再帰的なmutexと呼ばれています。非再帰的なもの(POSIX標準のようなもの)を好むなら、[here](http://stackoverflow.com/questions/1896581/how-do-i-make-the-mutex-not-be-recusive)forヒント – sehe

+0

私はGutaticRecMutexではなくGMutexを使用しているので、同じスレッドでGMutexを2回ロックするとデッドロックが作成され、mutexを2回ロックせずにGStaticRecMutexの場合と同じように処理されます。 – bbazso

関連する問題