Skip to content

Commit 0f4ecc0

Browse files
committed
fix multiple crash for qt6
1 parent 0453d0c commit 0f4ecc0

File tree

2 files changed

+93
-61
lines changed

2 files changed

+93
-61
lines changed

src/qt/automintmodel.cpp

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,57 +50,68 @@ void IncomingFundNotifier::pushTransaction(uint256 const &id)
5050

5151
void IncomingFundNotifier::check()
5252
{
53-
TRY_LOCK(cs, lock);
54-
if(!lock)
55-
return;
53+
// Phase 1: snapshot txs under local lock, enforce update interval
54+
std::vector<uint256> batch;
55+
const int64_t now = GetSystemTimeInSeconds();
56+
{
57+
TRY_LOCK(cs, lock);
58+
if (!lock)
59+
return;
5660

57-
// update only if there are transaction and last update was done more than 2 minutes ago, and in case it is first time
58-
if (txs.empty() || (lastUpdateTime!= 0 && (GetSystemTimeInSeconds() - lastUpdateTime <= 120))) {
59-
return;
60-
}
61+
if (txs.empty() || (lastUpdateTime != 0 && (now - lastUpdateTime <= 120))) {
62+
return;
63+
}
6164

62-
lastUpdateTime = GetSystemTimeInSeconds();
65+
lastUpdateTime = now;
66+
batch.swap(txs);
67+
}
6368

69+
// Phase 2: process under core locks (no IncomingFundNotifier::cs held)
6470
CAmount credit = 0;
6571
std::vector<uint256> immatures;
72+
CCoinControl coinControl;
73+
coinControl.nCoinType = CoinType::ONLY_NOT1000IFMN;
6674

6775
{
68-
TRY_LOCK(cs_main,lock_main);
69-
if (!lock_main)
76+
TRY_LOCK(cs_main, lock_main);
77+
if (!lock_main) {
78+
// Put back batch if we couldn't proceed
79+
LOCK(cs);
80+
txs.insert(txs.end(), batch.begin(), batch.end());
7081
return;
71-
TRY_LOCK(wallet->cs_wallet,lock_wallet);
72-
if (!lock_wallet)
82+
}
83+
TRY_LOCK(wallet->cs_wallet, lock_wallet);
84+
if (!lock_wallet) {
85+
LOCK(cs);
86+
txs.insert(txs.end(), batch.begin(), batch.end());
7387
return;
74-
CCoinControl coinControl;
75-
coinControl.nCoinType = CoinType::ONLY_NOT1000IFMN;
76-
while (!txs.empty()) {
77-
auto const &tx = txs.back();
78-
txs.pop_back();
79-
80-
auto wtx = wallet->mapWallet.find(tx);
81-
if (wtx == wallet->mapWallet.end()) {
88+
}
89+
90+
for (const auto& txid : batch) {
91+
auto it = wallet->mapWallet.find(txid);
92+
if (it == wallet->mapWallet.end())
8293
continue;
83-
}
8494

85-
for (uint32_t i = 0; i != wtx->second.tx->vout.size(); i++) {
86-
coinControl.Select({wtx->first, i});
95+
for (uint32_t i = 0; i != it->second.tx->vout.size(); ++i) {
96+
coinControl.Select({it->first, i});
8797
}
8898

89-
if (wtx->second.GetImmatureCredit() > 0) {
90-
immatures.push_back(tx);
99+
if (it->second.GetImmatureCredit() > 0) {
100+
immatures.push_back(txid);
91101
}
92102
}
93103

94104
std::vector<std::pair<CAmount, std::vector<COutput>>> valueAndUTXOs;
95105
pwalletMain->AvailableCoinsForLMint(valueAndUTXOs, &coinControl);
96-
97-
for (auto const &valueAndUTXO : valueAndUTXOs) {
98-
credit += valueAndUTXO.first;
106+
for (const auto& p : valueAndUTXOs) {
107+
credit += p.first;
99108
}
100109
}
101110

102-
for (auto const &tx : immatures) {
103-
txs.push_back(tx);
111+
// Phase 3: push back immatures under local lock
112+
if (!immatures.empty()) {
113+
LOCK(cs);
114+
txs.insert(txs.end(), immatures.begin(), immatures.end());
104115
}
105116

106117
if (credit > 0) {
@@ -110,16 +121,33 @@ void IncomingFundNotifier::check()
110121

111122
void IncomingFundNotifier::importTransactions()
112123
{
113-
LOCK2(cs, cs_main);
114-
LOCK(wallet->cs_wallet);
124+
// Gather under core locks only
125+
std::vector<uint256> to_add;
126+
{
127+
TRY_LOCK(cs_main, lock_main);
128+
if (!lock_main) {
129+
QTimer::singleShot(1000, this, &IncomingFundNotifier::importTransactions);
130+
return;
131+
}
132+
TRY_LOCK(wallet->cs_wallet, lock_wallet);
133+
if (!lock_wallet) {
134+
QTimer::singleShot(1000, this, &IncomingFundNotifier::importTransactions);
135+
return;
136+
}
115137

116-
for (auto const &tx : wallet->mapWallet) {
117-
if (tx.second.GetAvailableCredit() > 0 || tx.second.GetImmatureCredit() > 0) {
118-
txs.push_back(tx.first);
138+
for (const auto& it : wallet->mapWallet) {
139+
if (it.second.GetAvailableCredit() > 0 || it.second.GetImmatureCredit() > 0) {
140+
to_add.push_back(it.first);
141+
}
119142
}
120143
}
121144

122-
resetTimer();
145+
// Append under local lock, no core locks held
146+
{
147+
LOCK(cs);
148+
txs.insert(txs.end(), to_add.begin(), to_add.end());
149+
resetTimer();
150+
}
123151
}
124152

125153
void IncomingFundNotifier::resetTimer()

src/qt/notificator.cpp

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,32 @@
2727
#include "macnotificationhandler.h"
2828
#endif
2929

30+
#ifdef USE_DBUS
31+
// Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html
32+
class FreedesktopImage
33+
{
34+
public:
35+
FreedesktopImage() {}
36+
FreedesktopImage(const QImage &img);
37+
38+
static int metaType();
39+
40+
// Image to variant that can be marshalled over DBus
41+
static QVariant toVariant(const QImage &img);
42+
43+
private:
44+
int width, height, stride;
45+
bool hasAlpha;
46+
int channels;
47+
int bitsPerSample;
48+
QByteArray image;
49+
50+
friend QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i);
51+
friend const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i);
52+
};
53+
54+
Q_DECLARE_METATYPE(FreedesktopImage);
55+
#endif
3056

3157
#ifdef USE_DBUS
3258
// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
@@ -53,6 +79,9 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon
5379
if(interface->isValid())
5480
{
5581
mode = Freedesktop;
82+
// Make sure the custom DBus type is registered before use
83+
FreedesktopImage::metaType();
84+
// Alternatively: qDBusRegisterMetaType<FreedesktopImage>();
5685
}
5786
#endif
5887
#ifdef Q_OS_MAC
@@ -72,31 +101,6 @@ Notificator::~Notificator()
72101

73102
#ifdef USE_DBUS
74103

75-
// Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html
76-
class FreedesktopImage
77-
{
78-
public:
79-
FreedesktopImage() {}
80-
FreedesktopImage(const QImage &img);
81-
82-
static int metaType();
83-
84-
// Image to variant that can be marshalled over DBus
85-
static QVariant toVariant(const QImage &img);
86-
87-
private:
88-
int width, height, stride;
89-
bool hasAlpha;
90-
int channels;
91-
int bitsPerSample;
92-
QByteArray image;
93-
94-
friend QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i);
95-
friend const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i);
96-
};
97-
98-
Q_DECLARE_METATYPE(FreedesktopImage);
99-
100104
// Image configuration settings
101105
const int CHANNELS = 4;
102106
const int BYTES_PER_PIXEL = 4;

0 commit comments

Comments
 (0)