From ec3848c5ddfb08bffc19b055003a01a68da03daf Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 7 Aug 2015 07:08:37 +0300 Subject: [PATCH] Locks fixes: - trylock for updateDarksendProgress, checkBalanceChanged, "block" - trylock+wait for UnlockCoins, SendDarksendDenominate, ProcessNewBlock, ActivateBestChain - move trylock in DoAutomaticDenominating lower --- src/darksend.cpp | 33 +++++++++++++++++++-------------- src/main.cpp | 23 ++++++++++++----------- src/qt/overviewpage.cpp | 34 ++++++++++++++++++++++++---------- src/qt/sendcoinsdialog.cpp | 3 +++ src/qt/walletmodel.cpp | 3 +++ 5 files changed, 61 insertions(+), 35 deletions(-) diff --git a/src/darksend.cpp b/src/darksend.cpp index c26b0d2c0..38245ca7b 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -432,9 +432,13 @@ 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); + while(true) { + TRY_LOCK(pwalletMain->cs_wallet, lockWallet); + if(!lockWallet) {MilliSleep(10); continue;} + BOOST_FOREACH(CTxIn v, lockedCoins) + pwalletMain->UnlockCoin(v.prevout); + break; + } lockedCoins.clear(); } @@ -1155,14 +1159,16 @@ void CDarksendPool::SendDarksendDenominate(std::vector& vin, std::vector< LogPrintf("Submitting tx %s\n", tx.ToString()); - { - LOCK(cs_main); + while(true){ + TRY_LOCK(cs_main, lockMain); + if(!lockMain) { MilliSleep(10); continue;} if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)){ LogPrintf("dsi -- transaction not valid! %s \n", tx.ToString()); UnlockCoins(); SetNull(); return; } + break; } } @@ -1352,25 +1358,24 @@ void CDarksendPool::ClearLastMessage() // bool CDarksendPool::DoAutomaticDenominating(bool fDryRun, bool ready) { + if(!fEnableDarksend) return false; + if(fMasterNode) return false; + if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) return false; + if(GetEntriesCount() > 0) { + strAutoDenomResult = _("Mixing in progress..."); + return false; + } + TRY_LOCK(cs_darksend, lockDS); if(!lockDS) { strAutoDenomResult = _("Lock is already in place."); return false; } - LOCK(cs_darksend); - if(!masternodeSync.IsBlockchainSynced()) { strAutoDenomResult = _("Can't mix while sync in progress."); return false; } - if(!fEnableDarksend) return false; - if(fMasterNode) return false; - if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) return false; - if(GetEntriesCount() > 0) { - strAutoDenomResult = _("Mixing in progress..."); - return false; - } if (!fDryRun && pwalletMain->IsLocked()){ strAutoDenomResult = _("Wallet is locked."); diff --git a/src/main.cpp b/src/main.cpp index e15bd9fbb..76a5f8f9e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2616,8 +2616,10 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { boost::this_thread::interruption_point(); bool fInitialDownload; - { - LOCK(cs_main); + while(true) { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) { MilliSleep(10); continue; } + pindexMostWork = FindMostWorkChain(); // Whether we have anything to do at all. @@ -2629,6 +2631,7 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { pindexNewTip = chainActive.Tip(); fInitialDownload = IsInitialBlockDownload(); + break; } // When we reach this point, we switched to a new tip (stored in pindexNewTip). @@ -3261,8 +3264,10 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis // Preliminary checks bool checked = CheckBlock(*pblock, state); - { - LOCK(cs_main); + while(true) { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) { MilliSleep(10); continue; } + MarkBlockAsReceived(pblock->GetHash()); if (!checked) { return error("%s : CheckBlock FAILED", __func__); @@ -3277,6 +3282,7 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis CheckBlockIndex(); if (!ret) return error("%s : AcceptBlock FAILED", __func__); + break; } if (!ActivateBestChain(state, pblock)) @@ -4876,12 +4882,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlock block; vRecv >> block; - TRY_LOCK(cs_main, lockMainBlock); - if(!lockMainBlock && masternodeSync.IsBlockchainSynced()) { - LogPrintf("block -- failed to lock cs_main - %s\n", block.GetHash().ToString()); - return false; - } - CInv inv(MSG_BLOCK, block.GetHash()); LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom->id); @@ -4894,7 +4894,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); if (nDoS > 0) { - Misbehaving(pfrom->GetId(), nDoS); + TRY_LOCK(cs_main, lockMain); + if(lockMain) Misbehaving(pfrom->GetId(), nDoS); } } diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 688c5cb5d..840dfc06d 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -318,11 +318,10 @@ void OverviewPage::updateDarksendProgress() if(!pwalletMain) return; - int64_t nBalance = pwalletMain->GetBalance(); QString strAmountAndRounds; QString strAnonymizeDarkcoinAmount = BitcoinUnits::formatHtmlWithUnit(nDisplayUnit, nAnonymizeDarkcoinAmount * COIN, false, BitcoinUnits::separatorAlways); - if(nBalance == 0) + if(currentBalance == 0) { ui->darksendProgress->setValue(0); ui->darksendProgress->setToolTip(tr("No inputs detected")); @@ -336,9 +335,24 @@ void OverviewPage::updateDarksendProgress() return; } - int64_t nDenominatedUnconfirmedBalance = pwalletMain->GetDenominatedBalance(true); - int64_t nMaxToAnonymize = pwalletMain->GetAnonymizableBalance() + - pwalletMain->GetAnonymizedBalance() + nDenominatedUnconfirmedBalance; + CAmount nDenominatedConfirmedBalance; + CAmount nDenominatedUnconfirmedBalance; + CAmount nAnonymizableBalance; + CAmount nNormalizedAnonymizedBalance; + double nAverageAnonymizedRounds; + + { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) return; + + nDenominatedConfirmedBalance = pwalletMain->GetDenominatedBalance(); + nDenominatedUnconfirmedBalance = pwalletMain->GetDenominatedBalance(true); + nAnonymizableBalance = pwalletMain->GetAnonymizableBalance(); + nNormalizedAnonymizedBalance = pwalletMain->GetNormalizedAnonymizedBalance(); + nAverageAnonymizedRounds = pwalletMain->GetAverageAnonymizedRounds(); + } + + CAmount nMaxToAnonymize = nAnonymizableBalance + currentAnonymizedBalance + nDenominatedUnconfirmedBalance; // If it's more than the anon threshold, limit to that. if(nMaxToAnonymize > nAnonymizeDarkcoinAmount*COIN) nMaxToAnonymize = nAnonymizeDarkcoinAmount*COIN; @@ -371,16 +385,16 @@ void OverviewPage::updateDarksendProgress() // completeness of full amount anonimization float anonFullPart = 0; - int64_t denominatedBalance = pwalletMain->GetDenominatedBalance() + nDenominatedUnconfirmedBalance; + CAmount denominatedBalance = nDenominatedConfirmedBalance + nDenominatedUnconfirmedBalance; denomPart = (float)denominatedBalance / nMaxToAnonymize; denomPart = denomPart > 1 ? 1 : denomPart; denomPart *= 100; - anonNormPart = (float)pwalletMain->GetNormalizedAnonymizedBalance() / nMaxToAnonymize; + anonNormPart = (float)nNormalizedAnonymizedBalance / nMaxToAnonymize; anonNormPart = anonNormPart > 1 ? 1 : anonNormPart; anonNormPart *= 100; - anonFullPart = (float)pwalletMain->GetAnonymizedBalance() / nMaxToAnonymize; + anonFullPart = (float)currentAnonymizedBalance / nMaxToAnonymize; anonFullPart = anonFullPart > 1 ? 1 : anonFullPart; anonFullPart *= 100; @@ -404,7 +418,7 @@ void OverviewPage::updateDarksendProgress() tr("Anonymized") + ": %4%
" + tr("Denominated inputs have %5 of %n rounds on average", "", nDarksendRounds)) .arg(progress).arg(denomPart).arg(anonNormPart).arg(anonFullPart) - .arg(pwalletMain->GetAverageAnonymizedRounds()); + .arg(nAverageAnonymizedRounds); ui->darksendProgress->setToolTip(strToolPip); } @@ -486,7 +500,7 @@ void OverviewPage::toggleDarksend(){ settings.setValue("hasMixed", "hasMixed"); } if(!fEnableDarksend){ - int64_t balance = pwalletMain->GetBalance(); + int64_t balance = currentBalance; float minAmount = 1.49 * COIN; if(balance < minAmount){ QString strMinAmount(BitcoinUnits::formatWithUnit(nDisplayUnit, minAmount)); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 042c62034..9f3fc57eb 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -580,6 +580,9 @@ void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfir void SendCoinsDialog::updateDisplayUnit() { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) return; + setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getAnonymizedBalance(), model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); CoinControlDialog::coinControl->useDarkSend = ui->checkUseDarksend->isChecked(); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e318954bc..82d272eb8 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -146,6 +146,9 @@ void WalletModel::pollBalanceChanged() void WalletModel::checkBalanceChanged() { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) return; + CAmount newBalance = getBalance(); CAmount newUnconfirmedBalance = getUnconfirmedBalance(); CAmount newImmatureBalance = getImmatureBalance();