From afd715286a4d31e7671976ae6a6746e6df11d558 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 30 Jul 2015 16:44:18 +0300 Subject: [PATCH] fix all kind of lock issues --- src/activemasternode.cpp | 2 + src/darksend.cpp | 38 ++++++++++------ src/init.cpp | 1 + src/instantx.cpp | 2 +- src/masternode-sync.cpp | 15 +++++-- src/masternode.cpp | 93 +++++++++++++++++++++------------------- src/masternodeman.cpp | 10 ++--- src/wallet.cpp | 3 +- 8 files changed, 97 insertions(+), 67 deletions(-) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 6a621c51f5b8b..94c80cffbaaa3 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -90,6 +90,7 @@ void CActiveMasternode::ManageStatus() return; } + LOCK(pwalletMain->cs_wallet); pwalletMain->LockCoin(vin.prevout); // send to all nodes @@ -342,6 +343,7 @@ vector CActiveMasternode::SelectCoinsMasternode() vector filteredCoins; vector confLockedCoins; + LOCK(pwalletMain->cs_wallet); // Temporary unlock MN coins from masternode.conf if(GetBoolArg("-mnconflock", true)) { uint256 mnTxHash; diff --git a/src/darksend.cpp b/src/darksend.cpp index 6f54864e44367..08b40aee2f69c 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -259,11 +259,14 @@ void CDarksendPool::ProcessMessageDarksend(CNode* pfrom, std::string& strCommand return; } - if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)) { - LogPrintf("dsi -- transaction not valid! \n"); - errorID = ERR_INVALID_TX; - pfrom->PushMessage("dssu", sessionID, GetState(), GetEntriesCount(), MASTERNODE_REJECTED, errorID); - return; + { + LOCK(cs_main); + if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)) { + LogPrintf("dsi -- transaction not valid! \n"); + errorID = ERR_INVALID_TX; + pfrom->PushMessage("dssu", sessionID, GetState(), GetEntriesCount(), MASTERNODE_REJECTED, errorID); + return; + } } } @@ -429,6 +432,7 @@ bool CDarksendPool::SetCollateralAddress(std::string strAddress){ // Unlock coins after Darksend fails or succeeds // void CDarksendPool::UnlockCoins(){ + LOCK(pwalletMain->cs_wallet); BOOST_FOREACH(CTxIn v, lockedCoins) pwalletMain->UnlockCoin(v.prevout); @@ -967,10 +971,13 @@ bool CDarksendPool::IsCollateralValid(const CTransaction& txCollateral){ if(fDebug) LogPrintf("CDarksendPool::IsCollateralValid %s\n", txCollateral.ToString().c_str()); - CValidationState state; - if(!AcceptableInputs(mempool, state, txCollateral, true, NULL)){ - if(fDebug) LogPrintf ("CDarksendPool::IsCollateralValid - didn't pass IsAcceptable\n"); - return false; + { + LOCK(cs_main); + CValidationState state; + if(!AcceptableInputs(mempool, state, txCollateral, true, NULL)){ + if(fDebug) LogPrintf ("CDarksendPool::IsCollateralValid - didn't pass IsAcceptable\n"); + return false; + } } return true; @@ -1147,11 +1154,14 @@ void CDarksendPool::SendDarksendDenominate(std::vector& vin, std::vector< LogPrintf("Submitting tx %s\n", tx.ToString().c_str()); - if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)){ - LogPrintf("dsi -- transaction not valid! %s \n", tx.ToString().c_str()); - UnlockCoins(); - SetNull(); - return; + { + LOCK(cs_main); + if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)){ + LogPrintf("dsi -- transaction not valid! %s \n", tx.ToString().c_str()); + UnlockCoins(); + SetNull(); + return; + } } } diff --git a/src/init.cpp b/src/init.cpp index f1995b598189b..0e14420bcddfa 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1499,6 +1499,7 @@ bool AppInit2(boost::thread_group& threadGroup) strBudgetMode = GetArg("-budgetvotemode", "auto"); if(GetBoolArg("-mnconflock", true)) { + LOCK(pwalletMain->cs_wallet); LogPrintf("Locking Masternodes:\n"); uint256 mnTxHash; BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) { diff --git a/src/instantx.cpp b/src/instantx.cpp index 33b2249aaa128..588a3914686a2 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -70,7 +70,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& bool fMissingInputs = false; CValidationState state; - + LOCK(cs_main); if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { vector vInv; diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index 06a963df3f82c..deaa3f0b06dfc 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -157,7 +157,9 @@ void CMasternodeSync::ProcessMessage(CNode* pfrom, std::string& strCommand, CDat void CMasternodeSync::ClearFulfilledRequest() { - LOCK(cs_vNodes); + TRY_LOCK(cs_vNodes, lockRecv); + if(!lockRecv) return; + BOOST_FOREACH(CNode* pnode, vNodes) { pnode->ClearFulfilledRequest("getspork"); @@ -198,7 +200,9 @@ void CMasternodeSync::Process() if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset(); - LOCK(cs_vNodes); + TRY_LOCK(cs_vNodes, lockRecv); + if(!lockRecv) return; + BOOST_FOREACH(CNode* pnode, vNodes) { if(Params().NetworkID() == CBaseChainParams::REGTEST){ @@ -230,7 +234,12 @@ void CMasternodeSync::Process() return; } - if(IsInitialBlockDownload()) return; + { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) return; + + if(IsInitialBlockDownload()) return; + } //don't begin syncing until we're almost at a recent block if(pindexPrev->nTime + 600 < GetTime()) return; diff --git a/src/masternode.cpp b/src/masternode.cpp index 0587ef401bd42..a976a36cd9883 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -177,10 +177,6 @@ void CMasternode::Check() { if(ShutdownRequested()) return; - //TODO: Random segfault with this line removed - TRY_LOCK(cs_main, lockRecv); - if(!lockRecv) return; - //once spent, stop doing the checks if(activeState == MASTERNODE_VIN_SPENT) return; @@ -202,9 +198,15 @@ void CMasternode::Check() tx.vin.push_back(vin); tx.vout.push_back(vout); - if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)){ - activeState = MASTERNODE_VIN_SPENT; - return; + { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) return; + + if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)){ + activeState = MASTERNODE_VIN_SPENT; + return; + + } } } @@ -425,53 +427,58 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); - if(AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)){ - if(fDebug) LogPrintf("mnb - Accepted Masternode entry\n"); - if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ - LogPrintf("mnb - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); + { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) return false; + + if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)) { + //set nDos + state.IsInvalid(nDoS); return false; } + } - // verify that sig time is legit in past - // should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS - uint256 hashBlock = 0; - CTransaction tx2; - GetTransaction(vin.prevout.hash, tx2, hashBlock, true); - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) - { - CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation - CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS - if(pConfIndex->GetBlockTime() > sigTime) - { - LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n", - sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()); - return false; - } - } + if(fDebug) LogPrintf("mnb - Accepted Masternode entry\n"); - LogPrintf("mnb - Got NEW Masternode entry - %s - %s - %s - %lli \n", GetHash().ToString(), addr.ToString(), vin.ToString(), sigTime); - CMasternode mn(*this); - mnodeman.Add(mn); + if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ + LogPrintf("mnb - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); + return false; + } - // if it matches our Masternode privkey, then we've been remotely activated - if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ - activeMasternode.EnableHotColdMasterNode(vin, addr); + // verify that sig time is legit in past + // should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS + uint256 hashBlock = 0; + CTransaction tx2; + GetTransaction(vin.prevout.hash, tx2, hashBlock, true); + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation + CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS + if(pConfIndex->GetBlockTime() > sigTime) + { + LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n", + sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()); + return false; } + } - bool isLocal = addr.IsRFC1918() || addr.IsLocal(); - if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; - - if(!isLocal) Relay(); + LogPrintf("mnb - Got NEW Masternode entry - %s - %s - %s - %lli \n", GetHash().ToString(), addr.ToString(), vin.ToString(), sigTime); + CMasternode mn(*this); + mnodeman.Add(mn); - return true; - } else { - //set nDos - state.IsInvalid(nDoS); + // if it matches our Masternode privkey, then we've been remotely activated + if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ + activeMasternode.EnableHotColdMasterNode(vin, addr); } - return false; + bool isLocal = addr.IsRFC1918() || addr.IsLocal(); + if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; + + if(!isLocal) Relay(); + + return true; } void CMasternodeBroadcast::Relay() diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 68c25edcf6fe8..dbe699844c491 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -224,10 +224,10 @@ void CMasternodeMan::Check() void CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval) { - LOCK(cs); - Check(); + LOCK(cs); + //remove inactive and outdated vector::iterator it = vMasternodes.begin(); while(it != vMasternodes.end()){ @@ -604,17 +604,17 @@ void CMasternodeMan::ProcessMasternodeConnections() //we don't care about this for regtest if(Params().NetworkID() == CBaseChainParams::REGTEST) return; - LOCK(cs_vNodes); - if(!darkSendPool.pSubmittedToMasternode) return; + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) { if(darkSendPool.pSubmittedToMasternode->addr == pnode->addr) continue; if(pnode->fDarkSendMaster){ LogPrintf("Closing Masternode connection %s \n", pnode->addr.ToString().c_str()); - pnode->CloseSocketDisconnect(); + pnode->fDisconnect = true; } } } diff --git a/src/wallet.cpp b/src/wallet.cpp index 57bf2b78d722c..88d5562d8743e 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -2434,7 +2434,8 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds) LogPrintf("PrepareDarksendDenominate - preparing darksend denominate . Got: %d \n", nValueIn); - BOOST_FOREACH(CTxIn v, vCoins) + LOCK(cs_wallet); + BOOST_FOREACH(CTxIn v, vCoins) LockCoin(v.prevout); int64_t nValueLeft = nValueIn;