lbrycrd/src/reverselock.h
Cory Fields 89f71c68c0 c++11: don't throw from the reverselock destructor
noexcept is default for destructors as of c++11. By throwing in reverselock's
destructor if it's lock has been tampered with, the likely result is
std::terminate being called. Indeed that happened before this change.

Once reverselock has taken another lock (its ctor didn't throw), it makes no
sense to try to grab or lock the parent lock. That is be broken/undefined
behavior depending on the parent lock's implementation, but it shouldn't cause
the reverselock to fail to re-lock when destroyed.

To avoid those problems, simply swap the parent lock's contents with a dummy
for the duration of the lock. That will ensure that any undefined behavior is
caught at the call-site rather than the reverse lock's destruction.

Barring a failed mutex unlock which would be indicative of a larger problem,
the destructor should now never throw.
2016-01-05 17:17:29 -05:00

34 lines
759 B
C++

// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_REVERSELOCK_H
#define BITCOIN_REVERSELOCK_H
/**
* An RAII-style reverse lock. Unlocks on construction and locks on destruction.
*/
template<typename Lock>
class reverse_lock
{
public:
explicit reverse_lock(Lock& lock) : lock(lock) {
lock.unlock();
lock.swap(templock);
}
~reverse_lock() {
templock.lock();
templock.swap(lock);
}
private:
reverse_lock(reverse_lock const&);
reverse_lock& operator=(reverse_lock const&);
Lock& lock;
Lock templock;
};
#endif // BITCOIN_REVERSELOCK_H