Merge #10866: Fix -Wthread-safety-analysis warnings. Compile with -Wthread-safety-analysis if available.
76ea17c79
Add mutex requirement for AddToCompactExtraTransactions(…) (practicalswift)4616c825a
Use -Wthread-safety-analysis if available (+ -Werror=thread-safety-analysis if --enable-werror) (practicalswift)7e319d639
Fix -Wthread-safety-analysis warnings. Change the sync.h primitives to std from boost. (Matt Corallo) Pull request description: * Add mutex requirement for `AddToCompactExtraTransactions(…)`. * Use `-Wthread-safety-analysis` if available. * Rebased on top of https://github.com/TheBlueMatt/bitcoin/commits/2017-08-test-10923 - now includes: Fix -Wthread-safety-analysis warnings. Change the sync.h primitives to std from boost. Tree-SHA512: fb7365f85daa2741c276a1c899228181a8d46af51db7fbbdffceeaff121a3eb2ab74d7c8bf5e7de879bcc5042d00d24cb4649c312d51caba45a3f6135fd8b38f
This commit is contained in:
commit
ef8a634358
5 changed files with 35 additions and 31 deletions
|
@ -241,6 +241,7 @@ if test "x$enable_werror" = "xyes"; then
|
||||||
AC_MSG_ERROR("enable-werror set but -Werror is not usable")
|
AC_MSG_ERROR("enable-werror set but -Werror is not usable")
|
||||||
fi
|
fi
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=vla],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=vla"],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-Werror=vla],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=vla"],,[[$CXXFLAG_WERROR]])
|
||||||
|
AX_CHECK_COMPILE_FLAG([-Werror=thread-safety-analysis],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=thread-safety-analysis"],,[[$CXXFLAG_WERROR]])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$CXXFLAGS_overridden" = "xno"; then
|
if test "x$CXXFLAGS_overridden" = "xno"; then
|
||||||
|
@ -249,6 +250,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
|
||||||
AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
|
||||||
|
AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[CXXFLAGS="$CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
|
||||||
|
|
||||||
## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
|
## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
|
||||||
## unknown options if any other warning is produced. Test the -Wfoo case, and
|
## unknown options if any other warning is produced. Test the -Wfoo case, and
|
||||||
|
|
|
@ -544,14 +544,14 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool fHaveGenesis = false;
|
static bool fHaveGenesis = false;
|
||||||
static boost::mutex cs_GenesisWait;
|
static CWaitableCriticalSection cs_GenesisWait;
|
||||||
static CConditionVariable condvar_GenesisWait;
|
static CConditionVariable condvar_GenesisWait;
|
||||||
|
|
||||||
static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
|
static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
|
||||||
{
|
{
|
||||||
if (pBlockIndex != nullptr) {
|
if (pBlockIndex != nullptr) {
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock_GenesisWait(cs_GenesisWait);
|
WaitableLock lock_GenesisWait(cs_GenesisWait);
|
||||||
fHaveGenesis = true;
|
fHaveGenesis = true;
|
||||||
}
|
}
|
||||||
condvar_GenesisWait.notify_all();
|
condvar_GenesisWait.notify_all();
|
||||||
|
@ -1630,7 +1630,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
|
|
||||||
// Wait for genesis block to be processed
|
// Wait for genesis block to be processed
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(cs_GenesisWait);
|
WaitableLock lock(cs_GenesisWait);
|
||||||
while (!fHaveGenesis) {
|
while (!fHaveGenesis) {
|
||||||
condvar_GenesisWait.wait(lock);
|
condvar_GenesisWait.wait(lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,7 +633,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
|
||||||
// mapOrphanTransactions
|
// mapOrphanTransactions
|
||||||
//
|
//
|
||||||
|
|
||||||
void AddToCompactExtraTransactions(const CTransactionRef& tx)
|
void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
size_t max_extra_txn = gArgs.GetArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN);
|
size_t max_extra_txn = gArgs.GetArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN);
|
||||||
if (max_extra_txn <= 0)
|
if (max_extra_txn <= 0)
|
||||||
|
|
|
@ -455,7 +455,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
|
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
|
||||||
uint256 hashWatchedChain;
|
uint256 hashWatchedChain;
|
||||||
boost::system_time checktxtime;
|
std::chrono::steady_clock::time_point checktxtime;
|
||||||
unsigned int nTransactionsUpdatedLastLP;
|
unsigned int nTransactionsUpdatedLastLP;
|
||||||
|
|
||||||
if (lpval.isStr())
|
if (lpval.isStr())
|
||||||
|
@ -476,17 +476,17 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
// Release the wallet and main lock while waiting
|
// Release the wallet and main lock while waiting
|
||||||
LEAVE_CRITICAL_SECTION(cs_main);
|
LEAVE_CRITICAL_SECTION(cs_main);
|
||||||
{
|
{
|
||||||
checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
|
checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
|
||||||
|
|
||||||
boost::unique_lock<boost::mutex> lock(csBestBlock);
|
WaitableLock lock(csBestBlock);
|
||||||
while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
|
while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
|
||||||
{
|
{
|
||||||
if (!cvBlockChange.timed_wait(lock, checktxtime))
|
if (cvBlockChange.wait_until(lock, checktxtime) == std::cv_status::timeout)
|
||||||
{
|
{
|
||||||
// Timeout: Check transactions for update
|
// Timeout: Check transactions for update
|
||||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
||||||
break;
|
break;
|
||||||
checktxtime += boost::posix_time::seconds(10);
|
checktxtime += std::chrono::seconds(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
src/sync.h
46
src/sync.h
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
#include <boost/thread/condition_variable.hpp>
|
#include <boost/thread/condition_variable.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/recursive_mutex.hpp>
|
#include <condition_variable>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
@ -21,17 +23,17 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CCriticalSection mutex;
|
CCriticalSection mutex;
|
||||||
boost::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
LOCK(mutex);
|
LOCK(mutex);
|
||||||
boost::unique_lock<boost::recursive_mutex> criticalblock(mutex);
|
std::unique_lock<std::recursive_mutex> criticalblock(mutex);
|
||||||
|
|
||||||
LOCK2(mutex1, mutex2);
|
LOCK2(mutex1, mutex2);
|
||||||
boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1);
|
std::unique_lock<std::recursive_mutex> criticalblock1(mutex1);
|
||||||
boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2);
|
std::unique_lock<std::recursive_mutex> criticalblock2(mutex2);
|
||||||
|
|
||||||
TRY_LOCK(mutex, name);
|
TRY_LOCK(mutex, name);
|
||||||
boost::unique_lock<boost::recursive_mutex> name(mutex, boost::try_to_lock_t);
|
std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t);
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION(mutex); // no RAII
|
ENTER_CRITICAL_SECTION(mutex); // no RAII
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
|
@ -85,10 +87,10 @@ void static inline DeleteLock(void* cs) {}
|
||||||
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
|
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapped boost mutex: supports recursive locking, but no waiting
|
* Wrapped mutex: supports recursive locking, but no waiting
|
||||||
* TODO: We should move away from using the recursive lock by default.
|
* TODO: We should move away from using the recursive lock by default.
|
||||||
*/
|
*/
|
||||||
class CCriticalSection : public AnnotatedMixin<boost::recursive_mutex>
|
class CCriticalSection : public AnnotatedMixin<std::recursive_mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~CCriticalSection() {
|
~CCriticalSection() {
|
||||||
|
@ -96,22 +98,24 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Wrapped boost mutex: supports waiting but not recursive locking */
|
/** Wrapped mutex: supports waiting but not recursive locking */
|
||||||
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
|
typedef AnnotatedMixin<std::mutex> CWaitableCriticalSection;
|
||||||
|
|
||||||
/** Just a typedef for boost::condition_variable, can be wrapped later if desired */
|
/** Just a typedef for std::condition_variable, can be wrapped later if desired */
|
||||||
typedef boost::condition_variable CConditionVariable;
|
typedef std::condition_variable CConditionVariable;
|
||||||
|
|
||||||
|
/** Just a typedef for std::unique_lock, can be wrapped later if desired */
|
||||||
|
typedef std::unique_lock<std::mutex> WaitableLock;
|
||||||
|
|
||||||
#ifdef DEBUG_LOCKCONTENTION
|
#ifdef DEBUG_LOCKCONTENTION
|
||||||
void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
|
void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Wrapper around boost::unique_lock<Mutex> */
|
/** Wrapper around std::unique_lock<CCriticalSection> */
|
||||||
template <typename Mutex>
|
class SCOPED_LOCKABLE CCriticalBlock
|
||||||
class SCOPED_LOCKABLE CMutexLock
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
boost::unique_lock<Mutex> lock;
|
std::unique_lock<CCriticalSection> lock;
|
||||||
|
|
||||||
void Enter(const char* pszName, const char* pszFile, int nLine)
|
void Enter(const char* pszName, const char* pszFile, int nLine)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +140,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, boost::defer_lock)
|
CCriticalBlock(CCriticalSection& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, std::defer_lock)
|
||||||
{
|
{
|
||||||
if (fTry)
|
if (fTry)
|
||||||
TryEnter(pszName, pszFile, nLine);
|
TryEnter(pszName, pszFile, nLine);
|
||||||
|
@ -144,18 +148,18 @@ public:
|
||||||
Enter(pszName, pszFile, nLine);
|
Enter(pszName, pszFile, nLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
|
CCriticalBlock(CCriticalSection* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
|
||||||
{
|
{
|
||||||
if (!pmutexIn) return;
|
if (!pmutexIn) return;
|
||||||
|
|
||||||
lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock);
|
lock = std::unique_lock<CCriticalSection>(*pmutexIn, std::defer_lock);
|
||||||
if (fTry)
|
if (fTry)
|
||||||
TryEnter(pszName, pszFile, nLine);
|
TryEnter(pszName, pszFile, nLine);
|
||||||
else
|
else
|
||||||
Enter(pszName, pszFile, nLine);
|
Enter(pszName, pszFile, nLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CMutexLock() UNLOCK_FUNCTION()
|
~CCriticalBlock() UNLOCK_FUNCTION()
|
||||||
{
|
{
|
||||||
if (lock.owns_lock())
|
if (lock.owns_lock())
|
||||||
LeaveCritical();
|
LeaveCritical();
|
||||||
|
@ -167,8 +171,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef CMutexLock<CCriticalSection> CCriticalBlock;
|
|
||||||
|
|
||||||
#define PASTE(x, y) x ## y
|
#define PASTE(x, y) x ## y
|
||||||
#define PASTE2(x, y) PASTE(x, y)
|
#define PASTE2(x, y) PASTE(x, y)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue