Fix locking issues in dash-qt masternodelist (#1328)

* Add last ping time to masternode_info_t

* Use thread safe functions to access mnodeman in masternodelist.cpp

* Fix masternodelist widget locking

* Protect access to widget data from StartAlias button
This commit is contained in:
Tim Flynn 2017-02-09 19:56:52 -05:00 committed by UdjinM6
parent 4fcc766a29
commit 0b54ab85c8
4 changed files with 55 additions and 28 deletions

View File

@ -323,6 +323,7 @@ masternode_info_t CMasternode::GetInfo()
info.nTimeLastChecked = nTimeLastChecked;
info.nTimeLastPaid = nTimeLastPaid;
info.nTimeLastWatchdogVote = nTimeLastWatchdogVote;
info.nTimeLastPing = lastPing.sigTime;
info.nActiveState = nActiveState;
info.nProtocolVersion = nProtocolVersion;
info.fInfoValid = true;

View File

@ -112,6 +112,7 @@ struct masternode_info_t
nTimeLastChecked(0),
nTimeLastPaid(0),
nTimeLastWatchdogVote(0),
nTimeLastPing(0),
nActiveState(0),
nProtocolVersion(0),
fInfoValid(false)
@ -126,6 +127,7 @@ struct masternode_info_t
int64_t nTimeLastChecked;
int64_t nTimeLastPaid;
int64_t nTimeLastWatchdogVote;
int64_t nTimeLastPing;
int nActiveState;
int nProtocolVersion;
bool fInfoValid;

View File

@ -15,8 +15,6 @@
#include <QTimer>
#include <QMessageBox>
CCriticalSection cs_masternodes;
MasternodeList::MasternodeList(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent),
ui(new Ui::MasternodeList),
@ -132,10 +130,14 @@ void MasternodeList::StartAll(std::string strCommand)
std::string strError;
CMasternodeBroadcast mnb;
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(txin);
int32_t nOutputIndex = 0;
if(!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
continue;
}
if(strCommand == "start-missing" && pmn) continue;
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), nOutputIndex);
if(strCommand == "start-missing" && mnodeman.Has(txin)) continue;
bool fSuccess = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
@ -164,9 +166,8 @@ void MasternodeList::StartAll(std::string strCommand)
updateMyNodeList(true);
}
void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, CMasternode *pmn)
void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, masternode_info_t& infoMn)
{
LOCK(cs_mnlistupdate);
bool fOldRowFound = false;
int nNewRow = 0;
@ -184,12 +185,13 @@ void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, C
}
QTableWidgetItem *aliasItem = new QTableWidgetItem(strAlias);
QTableWidgetItem *addrItem = new QTableWidgetItem(pmn ? QString::fromStdString(pmn->addr.ToString()) : strAddr);
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(pmn ? pmn->nProtocolVersion : -1));
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(pmn ? pmn->GetStatus() : "MISSING"));
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(pmn ? (pmn->lastPing.sigTime - pmn->sigTime) : 0)));
QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M", pmn ? pmn->lastPing.sigTime + QDateTime::currentDateTime().offsetFromUtc() : 0)));
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(pmn ? CBitcoinAddress(pmn->pubKeyCollateralAddress.GetID()).ToString() : ""));
QTableWidgetItem *addrItem = new QTableWidgetItem(infoMn.fInfoValid ? QString::fromStdString(infoMn.addr.ToString()) : strAddr);
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(infoMn.fInfoValid ? infoMn.nProtocolVersion : -1));
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(infoMn.fInfoValid ? CMasternode::StateToString(infoMn.nActiveState) : "MISSING"));
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(infoMn.fInfoValid ? (infoMn.nTimeLastPing - infoMn.sigTime) : 0)));
QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M",
infoMn.fInfoValid ? infoMn.nTimeLastPing + QDateTime::currentDateTime().offsetFromUtc() : 0)));
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(infoMn.fInfoValid ? CBitcoinAddress(infoMn.pubKeyCollateralAddress.GetID()).ToString() : ""));
ui->tableWidgetMyMasternodes->setItem(nNewRow, 0, aliasItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 1, addrItem);
@ -202,6 +204,10 @@ void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, C
void MasternodeList::updateMyNodeList(bool fForce)
{
TRY_LOCK(cs_mymnlist, fLockAcquired);
if(!fLockAcquired) {
return;
}
static int64_t nTimeMyListUpdated = 0;
// automatically update my masternode list only once in MY_MASTERNODELIST_UPDATE_SECONDS seconds,
@ -214,10 +220,16 @@ void MasternodeList::updateMyNodeList(bool fForce)
ui->tableWidgetMasternodes->setSortingEnabled(false);
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(txin);
int32_t nOutputIndex = 0;
if(!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
continue;
}
updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), pmn);
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), nOutputIndex);
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(txin);
updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), infoMn);
}
ui->tableWidgetMasternodes->setSortingEnabled(true);
@ -227,6 +239,11 @@ void MasternodeList::updateMyNodeList(bool fForce)
void MasternodeList::updateNodeList()
{
TRY_LOCK(cs_mnlist, fLockAcquired);
if(!fLockAcquired) {
return;
}
static int64_t nTimeListUpdated = GetTime();
// to prevent high cpu usage update only once in MASTERNODELIST_UPDATE_SECONDS seconds
@ -241,9 +258,6 @@ void MasternodeList::updateNodeList()
nTimeListUpdated = GetTime();
fFilterUpdated = false;
TRY_LOCK(cs_masternodes, lockMasternodes);
if(!lockMasternodes) return;
QString strToFilter;
ui->countLabel->setText("Updating...");
ui->tableWidgetMasternodes->setSortingEnabled(false);
@ -296,15 +310,19 @@ void MasternodeList::on_filterLineEdit_textChanged(const QString &strFilterIn)
void MasternodeList::on_startButton_clicked()
{
// Find selected node alias
QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
QModelIndexList selected = selectionModel->selectedRows();
std::string strAlias;
{
LOCK(cs_mymnlist);
// Find selected node alias
QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
QModelIndexList selected = selectionModel->selectedRows();
if(selected.count() == 0) return;
if(selected.count() == 0) return;
QModelIndex index = selected.at(0);
int nSelectedRow = index.row();
std::string strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
QModelIndex index = selected.at(0);
int nSelectedRow = index.row();
strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
}
// Display message box
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm masternode start"),

View File

@ -45,7 +45,7 @@ private:
bool fFilterUpdated;
public Q_SLOTS:
void updateMyMasternodeInfo(QString strAlias, QString strAddr, CMasternode *pmn);
void updateMyMasternodeInfo(QString strAlias, QString strAddr, masternode_info_t& infoMn);
void updateMyNodeList(bool fForce = false);
void updateNodeList();
@ -56,7 +56,13 @@ private:
Ui::MasternodeList *ui;
ClientModel *clientModel;
WalletModel *walletModel;
CCriticalSection cs_mnlistupdate;
// Protects tableWidgetMasternodes
CCriticalSection cs_mnlist;
// Protects tableWidgetMyMasternodes
CCriticalSection cs_mymnlist;
QString strCurrentFilter;
private Q_SLOTS: