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:
parent
4fcc766a29
commit
0b54ab85c8
@ -323,6 +323,7 @@ masternode_info_t CMasternode::GetInfo()
|
|||||||
info.nTimeLastChecked = nTimeLastChecked;
|
info.nTimeLastChecked = nTimeLastChecked;
|
||||||
info.nTimeLastPaid = nTimeLastPaid;
|
info.nTimeLastPaid = nTimeLastPaid;
|
||||||
info.nTimeLastWatchdogVote = nTimeLastWatchdogVote;
|
info.nTimeLastWatchdogVote = nTimeLastWatchdogVote;
|
||||||
|
info.nTimeLastPing = lastPing.sigTime;
|
||||||
info.nActiveState = nActiveState;
|
info.nActiveState = nActiveState;
|
||||||
info.nProtocolVersion = nProtocolVersion;
|
info.nProtocolVersion = nProtocolVersion;
|
||||||
info.fInfoValid = true;
|
info.fInfoValid = true;
|
||||||
|
@ -112,6 +112,7 @@ struct masternode_info_t
|
|||||||
nTimeLastChecked(0),
|
nTimeLastChecked(0),
|
||||||
nTimeLastPaid(0),
|
nTimeLastPaid(0),
|
||||||
nTimeLastWatchdogVote(0),
|
nTimeLastWatchdogVote(0),
|
||||||
|
nTimeLastPing(0),
|
||||||
nActiveState(0),
|
nActiveState(0),
|
||||||
nProtocolVersion(0),
|
nProtocolVersion(0),
|
||||||
fInfoValid(false)
|
fInfoValid(false)
|
||||||
@ -126,6 +127,7 @@ struct masternode_info_t
|
|||||||
int64_t nTimeLastChecked;
|
int64_t nTimeLastChecked;
|
||||||
int64_t nTimeLastPaid;
|
int64_t nTimeLastPaid;
|
||||||
int64_t nTimeLastWatchdogVote;
|
int64_t nTimeLastWatchdogVote;
|
||||||
|
int64_t nTimeLastPing;
|
||||||
int nActiveState;
|
int nActiveState;
|
||||||
int nProtocolVersion;
|
int nProtocolVersion;
|
||||||
bool fInfoValid;
|
bool fInfoValid;
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
CCriticalSection cs_masternodes;
|
|
||||||
|
|
||||||
MasternodeList::MasternodeList(const PlatformStyle *platformStyle, QWidget *parent) :
|
MasternodeList::MasternodeList(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::MasternodeList),
|
ui(new Ui::MasternodeList),
|
||||||
@ -132,10 +130,14 @@ void MasternodeList::StartAll(std::string strCommand)
|
|||||||
std::string strError;
|
std::string strError;
|
||||||
CMasternodeBroadcast mnb;
|
CMasternodeBroadcast mnb;
|
||||||
|
|
||||||
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
|
int32_t nOutputIndex = 0;
|
||||||
CMasternode *pmn = mnodeman.Find(txin);
|
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);
|
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);
|
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;
|
bool fOldRowFound = false;
|
||||||
int nNewRow = 0;
|
int nNewRow = 0;
|
||||||
|
|
||||||
@ -184,12 +185,13 @@ void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, C
|
|||||||
}
|
}
|
||||||
|
|
||||||
QTableWidgetItem *aliasItem = new QTableWidgetItem(strAlias);
|
QTableWidgetItem *aliasItem = new QTableWidgetItem(strAlias);
|
||||||
QTableWidgetItem *addrItem = new QTableWidgetItem(pmn ? QString::fromStdString(pmn->addr.ToString()) : strAddr);
|
QTableWidgetItem *addrItem = new QTableWidgetItem(infoMn.fInfoValid ? QString::fromStdString(infoMn.addr.ToString()) : strAddr);
|
||||||
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(pmn ? pmn->nProtocolVersion : -1));
|
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(infoMn.fInfoValid ? infoMn.nProtocolVersion : -1));
|
||||||
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(pmn ? pmn->GetStatus() : "MISSING"));
|
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(infoMn.fInfoValid ? CMasternode::StateToString(infoMn.nActiveState) : "MISSING"));
|
||||||
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(pmn ? (pmn->lastPing.sigTime - pmn->sigTime) : 0)));
|
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", pmn ? pmn->lastPing.sigTime + QDateTime::currentDateTime().offsetFromUtc() : 0)));
|
QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M",
|
||||||
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(pmn ? CBitcoinAddress(pmn->pubKeyCollateralAddress.GetID()).ToString() : ""));
|
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, 0, aliasItem);
|
||||||
ui->tableWidgetMyMasternodes->setItem(nNewRow, 1, addrItem);
|
ui->tableWidgetMyMasternodes->setItem(nNewRow, 1, addrItem);
|
||||||
@ -202,6 +204,10 @@ void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, C
|
|||||||
|
|
||||||
void MasternodeList::updateMyNodeList(bool fForce)
|
void MasternodeList::updateMyNodeList(bool fForce)
|
||||||
{
|
{
|
||||||
|
TRY_LOCK(cs_mymnlist, fLockAcquired);
|
||||||
|
if(!fLockAcquired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
static int64_t nTimeMyListUpdated = 0;
|
static int64_t nTimeMyListUpdated = 0;
|
||||||
|
|
||||||
// automatically update my masternode list only once in MY_MASTERNODELIST_UPDATE_SECONDS seconds,
|
// 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);
|
ui->tableWidgetMasternodes->setSortingEnabled(false);
|
||||||
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
||||||
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
|
int32_t nOutputIndex = 0;
|
||||||
CMasternode *pmn = mnodeman.Find(txin);
|
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);
|
ui->tableWidgetMasternodes->setSortingEnabled(true);
|
||||||
|
|
||||||
@ -227,6 +239,11 @@ void MasternodeList::updateMyNodeList(bool fForce)
|
|||||||
|
|
||||||
void MasternodeList::updateNodeList()
|
void MasternodeList::updateNodeList()
|
||||||
{
|
{
|
||||||
|
TRY_LOCK(cs_mnlist, fLockAcquired);
|
||||||
|
if(!fLockAcquired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static int64_t nTimeListUpdated = GetTime();
|
static int64_t nTimeListUpdated = GetTime();
|
||||||
|
|
||||||
// to prevent high cpu usage update only once in MASTERNODELIST_UPDATE_SECONDS seconds
|
// to prevent high cpu usage update only once in MASTERNODELIST_UPDATE_SECONDS seconds
|
||||||
@ -241,9 +258,6 @@ void MasternodeList::updateNodeList()
|
|||||||
nTimeListUpdated = GetTime();
|
nTimeListUpdated = GetTime();
|
||||||
fFilterUpdated = false;
|
fFilterUpdated = false;
|
||||||
|
|
||||||
TRY_LOCK(cs_masternodes, lockMasternodes);
|
|
||||||
if(!lockMasternodes) return;
|
|
||||||
|
|
||||||
QString strToFilter;
|
QString strToFilter;
|
||||||
ui->countLabel->setText("Updating...");
|
ui->countLabel->setText("Updating...");
|
||||||
ui->tableWidgetMasternodes->setSortingEnabled(false);
|
ui->tableWidgetMasternodes->setSortingEnabled(false);
|
||||||
@ -296,15 +310,19 @@ void MasternodeList::on_filterLineEdit_textChanged(const QString &strFilterIn)
|
|||||||
|
|
||||||
void MasternodeList::on_startButton_clicked()
|
void MasternodeList::on_startButton_clicked()
|
||||||
{
|
{
|
||||||
// Find selected node alias
|
std::string strAlias;
|
||||||
QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
|
{
|
||||||
QModelIndexList selected = selectionModel->selectedRows();
|
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);
|
QModelIndex index = selected.at(0);
|
||||||
int nSelectedRow = index.row();
|
int nSelectedRow = index.row();
|
||||||
std::string strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
|
strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
// Display message box
|
// Display message box
|
||||||
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm masternode start"),
|
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm masternode start"),
|
||||||
|
@ -45,7 +45,7 @@ private:
|
|||||||
bool fFilterUpdated;
|
bool fFilterUpdated;
|
||||||
|
|
||||||
public Q_SLOTS:
|
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 updateMyNodeList(bool fForce = false);
|
||||||
void updateNodeList();
|
void updateNodeList();
|
||||||
|
|
||||||
@ -56,7 +56,13 @@ private:
|
|||||||
Ui::MasternodeList *ui;
|
Ui::MasternodeList *ui;
|
||||||
ClientModel *clientModel;
|
ClientModel *clientModel;
|
||||||
WalletModel *walletModel;
|
WalletModel *walletModel;
|
||||||
CCriticalSection cs_mnlistupdate;
|
|
||||||
|
// Protects tableWidgetMasternodes
|
||||||
|
CCriticalSection cs_mnlist;
|
||||||
|
|
||||||
|
// Protects tableWidgetMyMasternodes
|
||||||
|
CCriticalSection cs_mymnlist;
|
||||||
|
|
||||||
QString strCurrentFilter;
|
QString strCurrentFilter;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
Loading…
Reference in New Issue
Block a user