diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 41 | ||||
-rw-r--r-- | src/makefile.linux-mingw | 21 | ||||
-rw-r--r-- | src/makefile.mingw | 32 | ||||
-rw-r--r-- | src/makefile.osx | 4 | ||||
-rw-r--r-- | src/makefile.unix | 6 | ||||
-rw-r--r-- | src/net.cpp | 15 | ||||
-rw-r--r-- | src/net.h | 2 | ||||
-rw-r--r-- | src/rpc.cpp | 3 | ||||
-rw-r--r-- | src/test/script_tests.cpp | 136 | ||||
-rw-r--r-- | src/util.cpp | 118 | ||||
-rw-r--r-- | src/util.h | 56 |
11 files changed, 321 insertions, 113 deletions
diff --git a/src/main.cpp b/src/main.cpp index ee9165095a..f483312065 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1385,47 +1385,6 @@ bool static ProcessBlock(CNode* pfrom, CBlock* pblock) -template<typename Stream> -bool static ScanMessageStart(Stream& s) -{ - // Scan ahead to the next pchMessageStart, which should normally be immediately - // at the file pointer. Leaves file pointer at end of pchMessageStart. - s.clear(0); - short prevmask = s.exceptions(0); - const char* p = BEGIN(pchMessageStart); - try - { - loop - { - char c; - s.read(&c, 1); - if (s.fail()) - { - s.clear(0); - s.exceptions(prevmask); - return false; - } - if (*p != c) - p = BEGIN(pchMessageStart); - if (*p == c) - { - if (++p == END(pchMessageStart)) - { - s.clear(0); - s.exceptions(prevmask); - return true; - } - } - } - } - catch (...) - { - s.clear(0); - s.exceptions(prevmask); - return false; - } -} - bool CheckDiskSpace(uint64 nAdditionalBytes) { uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available; diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index e2ef4213aa..ddf9769055 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -7,19 +7,19 @@ DEPSDIR:=/usr/i586-mingw32msvc USE_UPNP:=0 INCLUDEPATHS= \ - -I"$(DEPSDIR)/boost_1_43_0" \ - -I"$(DEPSDIR)/db-4.7.25.NC/build_unix" \ + -I"$(DEPSDIR)/boost_1_47_0" \ + -I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \ -I"$(DEPSDIR)/openssl-1.0.0d/include" \ - -I"$(DEPSDIR)/wxWidgets-2.9.1/lib/gcc_lib/mswud" \ - -I"$(DEPSDIR)/wxWidgets-2.9.1/include" \ - -I"$(DEPSDIR)/wxWidgets-2.9.1/lib/wx/include/i586-mingw32msvc-msw-unicode-static-2.9/" \ + -I"$(DEPSDIR)/wxWidgets-2.9.2/lib/gcc_lib/mswud" \ + -I"$(DEPSDIR)/wxWidgets-2.9.2/include" \ + -I"$(DEPSDIR)/wxWidgets-2.9.2/lib/wx/include/i586-mingw32msvc-msw-unicode-static-2.9/" \ -I"$(DEPSDIR)" LIBPATHS= \ - -L"$(DEPSDIR)/boost_1_43_0/stage/lib" \ - -L"$(DEPSDIR)/db-4.7.25.NC/build_unix" \ + -L"$(DEPSDIR)/boost_1_47_0/stage/lib" \ + -L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \ -L"$(DEPSDIR)/openssl-1.0.0d" \ - -L"$(DEPSDIR)/wxWidgets-2.9.1/lib" + -L"$(DEPSDIR)/wxWidgets-2.9.2/lib" WXLIBS= -l wx_mswu-2.9-i586-mingw32msvc @@ -32,7 +32,7 @@ LIBS= \ -l ssl \ -l crypto -DEFS=-D_MT -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL +DEFS=-D_MT -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB DEBUGFLAGS=-g -D__WXDEBUG__ CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \ @@ -40,8 +40,7 @@ HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h crypter.h init.h ifdef USE_UPNP - INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215" - LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215" + LIBPATHS += -L"$(DEPSDIR)/miniupnpc" LIBS += -l miniupnpc -l iphlpapi DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) endif diff --git a/src/makefile.mingw b/src/makefile.mingw index 96f81b3067..05d0fd0cf7 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -5,31 +5,31 @@ USE_UPNP:=0 INCLUDEPATHS= \ - -I"C:\boost-1.43.0-mgw" \ - -I"C:\db-4.7.25.NC-mgw\build_unix" \ + -I"C:\boost-1.47.0-mgw" \ + -I"C:\db-4.8.30.NC-mgw\build_unix" \ -I"C:\openssl-1.0.0d-mgw\include" \ - -I"C:\wxWidgets-2.9.1-mgw\lib\gcc_lib\mswud" \ - -I"C:\wxWidgets-2.9.1-mgw\include" + -I"C:\wxWidgets-2.9.2-mgw\lib\gcc_lib\mswud" \ + -I"C:\wxWidgets-2.9.2-mgw\include" LIBPATHS= \ - -L"C:\boost-1.43.0-mgw\stage\lib" \ - -L"C:\db-4.7.25.NC-mgw\build_unix" \ + -L"C:\boost-1.47.0-mgw\stage\lib" \ + -L"C:\db-4.8.30.NC-mgw\build_unix" \ -L"C:\openssl-1.0.0d-mgw" \ - -L"C:\wxWidgets-2.9.1-mgw\lib\gcc_lib" + -L"C:\wxWidgets-2.9.2-mgw\lib\gcc_lib" WXLIBS= \ -l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd LIBS= \ - -l boost_system-mgw45-mt-s-1_43 \ - -l boost_filesystem-mgw45-mt-s-1_43 \ - -l boost_program_options-mgw45-mt-s-1_43 \ - -l boost_thread-mgw45-mt-s-1_43 \ + -l boost_system-mgw45-mt-s-1_47 \ + -l boost_filesystem-mgw45-mt-s-1_47 \ + -l boost_program_options-mgw45-mt-s-1_47 \ + -l boost_thread-mgw45-mt-s-1_47 \ -l db_cxx \ -l ssl \ -l crypto -DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL +DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB DEBUGFLAGS=-g -D__WXDEBUG__ CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \ @@ -37,8 +37,8 @@ HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h init.h crypter.h ifdef USE_UPNP - INCLUDEPATHS += -I"C:\upnpc-exe-win32-20110215" - LIBPATHS += -L"C:\upnpc-exe-win32-20110215" + INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw" + LIBPATHS += -L"C:\miniupnpc-1.6-mgw" LIBS += -l miniupnpc -l iphlpapi DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) endif @@ -83,8 +83,8 @@ obj/nogui/%.o: %.cpp $(HEADERS) bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/ui_res.o g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -obj/test/%.o: obj/test/%.cpp $(HEADERS) - g++ -c $(CFLAGS) -o $@ $< +obj/test/test_bitcoin.o: $(wildcard test/*.cpp) $(HEADERS) + g++ -c $(CFLAGS) -o $@ test/test_bitcoin.cpp test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%)) g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) diff --git a/src/makefile.osx b/src/makefile.osx index 699911d4e6..363a85fc7b 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -76,8 +76,8 @@ obj/nogui/%.o: %.cpp $(HEADERS) bitcoind: $(OBJS:obj/%=obj/nogui/%) $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -obj/test/%.o: test/%.cpp $(HEADERS) - $(CXX) -c $(CFLAGS) -o $@ $< +obj/test/test_bitcoin.o: $(wildcard test/*.cpp) $(HEADERS) + $(CXX) -c $(CFLAGS) -o $@ test/test_bitcoin.cpp test_bitcoin: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%)) $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lboost_unit_test_framework diff --git a/src/makefile.unix b/src/makefile.unix index ba9d0ca11d..597eea0dc8 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -10,7 +10,7 @@ WXLIBS=$(shell wx-config --libs) USE_UPNP:=0 -DEFS=-DNOPCH -DFOURWAYSSE2 -DUSE_SSL +DEFS=-DNOPCH -DUSE_SSL # for boost 1.37, add -mt to the boost libraries LIBS= \ @@ -77,8 +77,8 @@ obj/nogui/%.o: %.cpp $(HEADERS) bitcoind: $(OBJS:obj/%=obj/nogui/%) $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) -obj/test/%.o: test/%.cpp $(HEADERS) - $(CXX) -c $(CXXFLAGS) -o $@ $< +obj/test/test_bitcoin.o: $(wildcard test/*.cpp) $(HEADERS) + $(CXX) -c $(CFLAGS) -o $@ test/test_bitcoin.cpp test_bitcoin: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%)) $(CXX) $(CXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-Bstatic -lboost_unit_test_framework $(LIBS) diff --git a/src/net.cpp b/src/net.cpp index 3953f021e9..c498c40106 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -12,11 +12,6 @@ #ifdef __WXMSW__ #include <string.h> -// This file can be downloaded as a part of the Windows Platform SDK -// and is required for Bitcoin binaries to work properly on versions -// of Windows before XP. If you are doing builds of Bitcoin for -// public release, you should uncomment this line. -//#include <WSPiApi.h> #endif #ifdef USE_UPNP @@ -1079,10 +1074,11 @@ void ThreadMapPort2(void* parg) const char * rootdescurl = 0; const char * multicastif = 0; const char * minissdpdpath = 0; + int error = 0; struct UPNPDev * devlist = 0; char lanaddr[64]; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); + devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); struct UPNPUrls urls; struct IGDdatas data; @@ -1094,14 +1090,9 @@ void ThreadMapPort2(void* parg) char intClient[16]; char intPort[6]; string strDesc = "Bitcoin " + FormatFullVersion(); - -#ifndef __WXMSW__ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port, port, lanaddr, strDesc.c_str(), "TCP", 0); -#else r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0"); -#endif + if(r!=UPNPCOMMAND_SUCCESS) printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r)); @@ -677,7 +677,7 @@ public: void BeginMessage(const char* pszCommand) { - cs_vSend.Enter(); + cs_vSend.Enter("cs_vSend", __FILE__, __LINE__); if (nHeaderStart != -1) AbortMessage(); nHeaderStart = vSend.size(); diff --git a/src/rpc.cpp b/src/rpc.cpp index dd3430d42f..62b2f82fb1 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -1188,7 +1188,8 @@ Value listtransactions(const Array& params, bool fHelp) // Now: iterate backwards until we have nCount items to return: TxItems::reverse_iterator it = txByTime.rbegin(); - for (std::advance(it, nFrom); it != txByTime.rend(); ++it) + if (txByTime.size() > nFrom) std::advance(it, nFrom); + for (; it != txByTime.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; if (pwtx != 0) diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 5e74648c4b..13feb86b97 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -6,6 +6,9 @@ #include "../wallet.h" using namespace std; +extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType); BOOST_AUTO_TEST_SUITE(script_tests) @@ -34,4 +37,137 @@ BOOST_AUTO_TEST_CASE(script_PushData) BOOST_CHECK(pushdata4Stack == directStack); } +CScript +sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction) +{ + uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL); + + CScript result; + // + // NOTE: CHECKMULTISIG has an unfortunate bug; it requires + // one extra item on the stack, before the signatures. + // Putting OP_0 on the stack is the workaround; + // fixing the bug would mean splitting the blockchain (old + // clients would not accept new CHECKMULTISIG transactions, + // and vice-versa) + // + result << OP_0; + BOOST_FOREACH(CKey key, keys) + { + vector<unsigned char> vchSig; + BOOST_CHECK(key.Sign(hash, vchSig)); + vchSig.push_back((unsigned char)SIGHASH_ALL); + result << vchSig; + } + return result; +} +CScript +sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction) +{ + std::vector<CKey> keys; + keys.push_back(key); + return sign_multisig(scriptPubKey, keys, transaction); +} + +BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) +{ + CKey key1, key2, key3; + key1.MakeNewKey(); + key2.MakeNewKey(); + key3.MakeNewKey(); + + CScript scriptPubKey12; + scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG; + + CTransaction txFrom12; + txFrom12.vout.resize(1); + txFrom12.vout[0].scriptPubKey = scriptPubKey12; + + CTransaction txTo12; + txTo12.vin.resize(1); + txTo12.vout.resize(1); + txTo12.vin[0].prevout.n = 0; + txTo12.vin[0].prevout.hash = txFrom12.GetHash(); + txTo12.vout[0].nValue = 1; + + CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0)); + txTo12.vout[0].nValue = 2; + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0)); + + CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, 0)); + + CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, 0)); +} + +BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) +{ + CKey key1, key2, key3, key4; + key1.MakeNewKey(); + key2.MakeNewKey(); + key3.MakeNewKey(); + key4.MakeNewKey(); + + CScript scriptPubKey23; + scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG; + + CTransaction txFrom23; + txFrom23.vout.resize(1); + txFrom23.vout[0].scriptPubKey = scriptPubKey23; + + CTransaction txTo23; + txTo23.vin.resize(1); + txTo23.vout.resize(1); + txTo23.vin[0].prevout.n = 0; + txTo23.vin[0].prevout.hash = txFrom23.GetHash(); + txTo23.vout[0].nValue = 1; + + std::vector<CKey> keys; + keys.push_back(key1); keys.push_back(key2); + CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key1); keys.push_back(key3); + CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key2); keys.push_back(key3); + CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key2); keys.push_back(key2); // Can't re-use sig + CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order + CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order + CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys + CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); + keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys + CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, 0)); + + keys.clear(); // Must have signatures + CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, 0)); +} + + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.cpp b/src/util.cpp index 1784448fc8..24c7ed4487 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -909,4 +909,122 @@ string FormatFullVersion() +#ifdef DEBUG_LOCKORDER +// +// Early deadlock detection. +// Problem being solved: +// Thread 1 locks A, then B, then C +// Thread 2 locks D, then C, then A +// --> may result in deadlock between the two threads, depending on when they run. +// Solution implemented here: +// Keep track of pairs of locks: (A before B), (A before C), etc. +// Complain if any thread trys to lock in a different order. +// + +struct CLockLocation +{ + std::string mutexName; + std::string sourceFile; + int sourceLine; + + CLockLocation(const char* pszName, const char* pszFile, int nLine) + { + mutexName = pszName; + sourceFile = pszFile; + sourceLine = nLine; + } +}; + +typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack; + +static boost::interprocess::interprocess_mutex dd_mutex; +static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders; +static boost::thread_specific_ptr<LockStack> lockstack; + + +static void potential_deadlock_detected(const LockStack& s1, const LockStack& s2) +{ + printf("POTENTIAL DEADLOCK DETECTED\n"); + printf("Previous lock order was:\n"); + BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2) + { + printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine); + } + printf("Current lock order is:\n"); + BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1) + { + printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine); + } +} + +static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) +{ + bool fOrderOK = true; + if (lockstack.get() == NULL) + lockstack.reset(new LockStack); + + dd_mutex.lock(); + + (*lockstack).push_back(std::make_pair(c, locklocation)); + + BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack)) + { + if (i.first == c) break; + + std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c); + if (lockorders.count(p1)) + continue; + lockorders[p1] = (*lockstack); + + std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first); + if (lockorders.count(p2)) + { + potential_deadlock_detected(lockorders[p2], lockorders[p1]); + break; + } + } + dd_mutex.unlock(); +} + +static void pop_lock() +{ + (*lockstack).pop_back(); +} + +void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine) +{ + push_lock(this, CLockLocation(pszName, pszFile, nLine)); + mutex.lock(); +} +void CCriticalSection::Leave() +{ + mutex.unlock(); + pop_lock(); +} +bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine) +{ + push_lock(this, CLockLocation(pszName, pszFile, nLine)); + bool result = mutex.try_lock(); + if (!result) pop_lock(); + return result; +} + +#else + +void CCriticalSection::Enter(const char*, const char*, int) +{ + mutex.lock(); +} + +void CCriticalSection::Leave() +{ + mutex.unlock(); +} + +bool CCriticalSection::TryEnter(const char*, const char*, int) +{ + bool result = mutex.try_lock(); + return result; +} +#endif /* DEBUG_LOCKORDER */ diff --git a/src/util.h b/src/util.h index 77f08d7471..1e4ceb2468 100644 --- a/src/util.h +++ b/src/util.h @@ -223,31 +223,17 @@ std::string FormatFullVersion(); -// Wrapper to automatically initialize critical sections +// Wrapper to automatically initialize mutex class CCriticalSection { -#ifdef __WXMSW__ -protected: - CRITICAL_SECTION cs; -public: - explicit CCriticalSection() { InitializeCriticalSection(&cs); } - ~CCriticalSection() { DeleteCriticalSection(&cs); } - void Enter() { EnterCriticalSection(&cs); } - void Leave() { LeaveCriticalSection(&cs); } - bool TryEnter() { return TryEnterCriticalSection(&cs); } -#else protected: boost::interprocess::interprocess_recursive_mutex mutex; public: explicit CCriticalSection() { } ~CCriticalSection() { } - void Enter() { mutex.lock(); } - void Leave() { mutex.unlock(); } - bool TryEnter() { return mutex.try_lock(); } -#endif -public: - const char* pszFile; - int nLine; + void Enter(const char* pszName, const char* pszFile, int nLine); + void Leave(); + bool TryEnter(const char* pszName, const char* pszFile, int nLine); }; // Automatically leave critical section when leaving block, needed for exception safety @@ -255,9 +241,17 @@ class CCriticalBlock { protected: CCriticalSection* pcs; + public: - CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; pcs->Enter(); } - ~CCriticalBlock() { pcs->Leave(); } + CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + { + pcs = &csIn; + pcs->Enter(pszName, pszFile, nLine); + } + ~CCriticalBlock() + { + pcs->Leave(); + } }; // WARNING: This will catch continue and break! @@ -265,22 +259,32 @@ public: // I'd rather be careful than suffer the other more error prone syntax. // The compiler will optimise away all this loop junk. #define CRITICAL_BLOCK(cs) \ - for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \ - for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0) + for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \ + for (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false) class CTryCriticalBlock { protected: CCriticalSection* pcs; + public: - CTryCriticalBlock(CCriticalSection& csIn) { pcs = (csIn.TryEnter() ? &csIn : NULL); } - ~CTryCriticalBlock() { if (pcs) pcs->Leave(); } + CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + { + pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL); + } + ~CTryCriticalBlock() + { + if (pcs) + { + pcs->Leave(); + } + } bool Entered() { return pcs != NULL; } }; #define TRY_CRITICAL_BLOCK(cs) \ - for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \ - for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0) + for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \ + for (CTryCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()); fcriticalblockonce=false) |