Project Name | CID | Checker | Category | Developer Description |
---|---|---|---|---|
cryfs/cryfs | 1361500 | ORDER_REVERSAL | Program hangs | We had some spurious hangs and never knew why. I would never have thought of looking at this piece of code if coverity hadn't found it. |
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
LockPool(); ~LockPool(); void lock(const LockName &lock, std::unique_lock<std::mutex> *lockToFreeWhileWaiting = nullptr); void release(const LockName &lock); private: bool _isLocked(const LockName &lock) const; std::vector<LockName> _lockedLocks; std::mutex _mutex; std::condition_variable_any _cv; DISALLOW_COPY_AND_ASSIGN(LockPool); }; template<class LockName> inline LockPool<LockName>::LockPool(): _lockedLocks(), _mutex(), _cv() {} template<class LockName> inline LockPool<LockName>::~LockPool() { ASSERT(_lockedLocks.size() == 0, "Still locks open"); } template<class LockName> inline void LockPool<LockName>::lock(const LockName &lock, std::unique_lock<std::mutex> *lockToFreeWhileWaiting) { |
<<< CID 1361500: Program hangs ORDER_REVERSAL <<< 1. Calling "unique_lock" acquires lock "cpputils::LockPool<cpputils::FixedSizeData<16ul> >._mutex".
45 |
std::unique_lock<std::mutex> mutexLock(_mutex); // TODO Is shared_lock enough here? |
< 2. Condition "this->_isLocked(lock)", taking true branch.
46 47 48 49 50 |
if (_isLocked(lock)) { // Order of locking/unlocking is important and should be the same order as everywhere else to prevent deadlocks. // Since when entering the function, lockToFreeWhileWaiting is already locked and mutexLock is locked afterwards, // the condition variable should do it in the same order. We use combinedLock for this. CombinedLock combinedLock(lockToFreeWhileWaiting, &mutexLock); |
<<< CID 1361500: Program hangs ORDER_REVERSAL <<< 3. Calling "wait" acquires lock "std::unique_lock<std::mutex>._M_device" while holding lock "cpputils::LockPool<cpputils::FixedSizeData<16ul> >._mutex" (count: 1 / 2).
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
_cv.wait(combinedLock, [this, &lock]{ return !_isLocked(lock); }); ASSERT(mutexLock.owns_lock() && lockToFreeWhileWaiting->owns_lock(), "Locks haven't been correctly relocked"); } _lockedLocks.push_back(lock); } template<class LockName> inline bool LockPool<LockName>::_isLocked(const LockName &lock) const { return std::find(_lockedLocks.begin(), _lockedLocks.end(), lock) != _lockedLocks.end(); } template<class LockName> inline void LockPool<LockName>::release(const LockName &lock) { std::unique_lock<std::mutex> mutexLock(_mutex); auto found = std::find(_lockedLocks.begin(), _lockedLocks.end(), lock); ASSERT(found != _lockedLocks.end(), "Lock given to release() was not locked"); _lockedLocks.erase(found); _cv.notify_all(); } } #endif |
1. lock_acquire | Cache.h:114 | |
2. example_lock_order | Cache.h:115 | |
1. lock_acquire | LockPool.h:45 | |
3. lock_order | LockPool.h:51 |