From ff3cedd772e7daf5a11460aa1b87f24c01183159 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 2 May 2026 19:53:47 +0000 Subject: [PATCH] Fix Qt shutdown and Linux wallet build --- contrib/build-linux-wallet.sh | 27 +++++++++++++++++++-------- contrib/build-linux.sh | 16 +++++++++++----- depends/Makefile | 24 +++++++++++++++++------- depends/packages/qt.mk | 1 + src/miner.cpp | 8 ++++++-- src/qt/agrarian.cpp | 6 ++++-- src/wallet/walletdb.cpp | 3 ++- 7 files changed, 60 insertions(+), 25 deletions(-) diff --git a/contrib/build-linux-wallet.sh b/contrib/build-linux-wallet.sh index 83cef8fb..dde19143 100755 --- a/contrib/build-linux-wallet.sh +++ b/contrib/build-linux-wallet.sh @@ -142,6 +142,17 @@ remove_invalid_native_protobuf_cache() { rm -rf "$ROOT/depends/built/$HOST/native_protobuf" } +reset_configure_state() { + rm -f config.cache config.log config.status libtool + + # Stale generated makefiles and libtool scripts can trigger rechecks with + # old autotools/libtool macros after a failed or moved build. + find . \( -name Makefile -o -name config.status -o -name config.log -o -name libtool \) \ + ! -path './depends/*' \ + ! -path './.git/*' \ + -delete +} + cd "$ROOT" require_cmd make @@ -162,17 +173,17 @@ reset_qt_configure_state remove_invalid_native_protobuf_cache echo "Building native depends for $HOST..." -make -C depends HOST="$HOST" NO_QT=0 -j"$JOBS" +# The legacy depends system mutates depends/$HOST while configuring each +# package. Package-level parallelism can race and remove headers/libs another +# package is probing, so keep depends serial and use JOBS for the final wallet +# compile below. +make -C depends clean +make -C depends HOST="$HOST" NO_QT=0 -j1 require_path "$BASE_CONFIG" ensure_native_protoc -if [[ ! -f configure || ! -f src/secp256k1/configure || ! -f src/secp256k1/Makefile.in ]]; then - ./autogen.sh -fi - -if [[ build-aux/m4/bitcoin_qt.m4 -nt configure || build-aux/m4/bitcoin_qt.m4 -nt aclocal.m4 ]]; then - ./autogen.sh -fi +reset_configure_state +./autogen.sh echo "Configuring Ubuntu Qt6 wallet build..." QT_SYSTEM_PKG_CONFIG_LIBDIR="$QT_SYSTEM_PKG_CONFIG_LIBDIR" CONFIG_SITE="$BASE_CONFIG" ./configure \ diff --git a/contrib/build-linux.sh b/contrib/build-linux.sh index 2104a618..360f69a8 100755 --- a/contrib/build-linux.sh +++ b/contrib/build-linux.sh @@ -16,11 +16,12 @@ require_path() { } reset_configure_state() { - rm -f config.cache config.log config.status + rm -f config.cache config.log config.status libtool - # Stale generated makefiles can trigger config.status --recheck with old - # configure arguments after a failed build attempt. - find . -name Makefile -type f \ + # Stale generated makefiles and libtool scripts can trigger rechecks with + # old configure arguments or old autotools/libtool macros after a failed + # build attempt. + find . \( -name Makefile -o -name config.status -o -name config.log -o -name libtool \) \ ! -path './depends/*' \ ! -path './.git/*' \ -delete @@ -31,7 +32,12 @@ cd "$ROOT" case "$MODE" in daemon) echo "Building native daemon depends for $HOST..." - make -C depends HOST="$HOST" NO_QT=1 -j"$JOBS" + # The legacy depends system mutates depends/$HOST while configuring each + # package, so package-level parallelism can race and remove headers/libs + # another package is probing. Keep depends serial; use JOBS for the final + # Agrarian compile below. + make -C depends clean + make -C depends HOST="$HOST" NO_QT=1 -j1 require_path "$BASE_CONFIG" reset_configure_state diff --git a/depends/Makefile b/depends/Makefile index 594800e6..c99d25eb 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -94,11 +94,16 @@ install-prefix: $(packages) shopt -s nullglob; \ for p in $(packages); do \ artifacts=( "$(BASE_CACHE)/$(HOST)/$$p/"*.tar.gz ); \ - if (( $${#artifacts[@]} != 1 )); then \ - echo "ERROR: expected exactly one built artifact for $$p under $(BASE_CACHE)/$(HOST)/$$p"; \ + if (( $${#artifacts[@]} == 0 )); then \ + echo "ERROR: expected a built artifact for $$p under $(BASE_CACHE)/$(HOST)/$$p"; \ exit 1; \ fi; \ - f="$${artifacts[0]}"; \ + if (( $${#artifacts[@]} > 1 )); then \ + echo "WARN: multiple built artifacts for $$p; using newest by name"; \ + fi; \ + IFS=$$'\n' sorted=( $$(printf '%s\n' "$${artifacts[@]}" | sort) ); \ + unset IFS; \ + f="$${sorted[$$(($${#sorted[@]} - 1))]}"; \ echo " - $$p: $$f"; \ tar --no-same-owner -xzf "$$f" -C "$(host_prefix)"; \ done @@ -110,11 +115,16 @@ ifneq ($(native_packages),) shopt -s nullglob; \ for p in $(native_packages); do \ artifacts=( "$(BASE_CACHE)/$(HOST)/$$p/"*.tar.gz ); \ - if (( $${#artifacts[@]} != 1 )); then \ - echo "ERROR: expected exactly one built artifact for $$p under $(BASE_CACHE)/$(HOST)/$$p"; \ + if (( $${#artifacts[@]} == 0 )); then \ + echo "ERROR: expected a built artifact for $$p under $(BASE_CACHE)/$(HOST)/$$p"; \ exit 1; \ fi; \ - f="$${artifacts[0]}"; \ + if (( $${#artifacts[@]} > 1 )); then \ + echo "WARN: multiple built artifacts for $$p; using newest by name"; \ + fi; \ + IFS=$$'\n' sorted=( $$(printf '%s\n' "$${artifacts[@]}" | sort) ); \ + unset IFS; \ + f="$${sorted[$$(($${#sorted[@]} - 1))]}"; \ echo " - $$p: $$f"; \ tar --no-same-owner -xzf "$$f" -C "$(build_prefix)"; \ done @@ -166,7 +176,7 @@ endif echo "PATH=\"$(build_prefix)/bin:\$$PATH\""; \ echo "PKG_CONFIG='`which pkg-config` --static'"; \ echo "PKG_CONFIG_LIBDIR='$(host_prefix)/lib/pkgconfig:$(host_prefix)/share/pkgconfig'"; \ - echo "PKG_CONFIG_PATH=\"$$PKG_CONFIG_LIBDIR\""; \ + echo "PKG_CONFIG_PATH=\"\$$PKG_CONFIG_LIBDIR\""; \ echo "export PKG_CONFIG_LIBDIR"; \ echo "export PKG_CONFIG_PATH"; \ echo "export PKG_CONFIG"; \ diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 09987510..509a6665 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -28,6 +28,7 @@ $(package)_config_opts += -no-glib $(package)_config_opts += -no-icu $(package)_config_opts += -no-opengl $(package)_config_opts += -no-pch +$(package)_config_opts += -no-feature-brotli $(package)_config_opts += -no-feature-sql $(package)_config_opts += -no-feature-vulkan $(package)_config_opts += -nomake examples diff --git a/src/miner.cpp b/src/miner.cpp index 4ca576ef..2a222f2e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -10,6 +10,7 @@ #include "amount.h" #include "hash.h" +#include "init.h" #include "main.h" #include "masternode-sync.h" #include "net.h" @@ -634,7 +635,7 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake) CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; bool fLastLoopOrphan = false; - while (fGenerateBitcoins || fProofOfStake) { + while ((fGenerateBitcoins || fProofOfStake) && !ShutdownRequested()) { if (fProofOfStake) { //control the amount of times the client will check for mintable coins if ((GetTime() - nMintableLastCheck > 5 * 60)) // 5 minute check time @@ -648,7 +649,7 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake) continue; } - while (vNodes.empty() || pwallet->IsLocked() || !fMintableCoins || (pwallet->GetBalance() > 0 && nReserveBalance >= pwallet->GetBalance()) || !masternodeSync.IsSynced()) { + while (!ShutdownRequested() && (vNodes.empty() || pwallet->IsLocked() || !fMintableCoins || (pwallet->GetBalance() > 0 && nReserveBalance >= pwallet->GetBalance()) || !masternodeSync.IsSynced())) { nLastCoinStakeSearchInterval = 0; // Do a separate 1 minute check here to ensure fMintableCoins is updated if (!fMintableCoins) { @@ -662,6 +663,8 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake) if (!fGenerateBitcoins && !fProofOfStake) continue; } + if (ShutdownRequested()) + break; if (mapHashedBlocks.count(chainActive.Tip()->nHeight) && !fLastLoopOrphan) //search our map of hashed blocks, see if bestblock has been hashed yet { @@ -834,6 +837,7 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) if (minerThreads != nullptr) { minerThreads->interrupt_all(); + minerThreads->join_all(); delete minerThreads; minerThreads = nullptr; } diff --git a/src/qt/agrarian.cpp b/src/qt/agrarian.cpp index 8c0cdcd7..4f0dc6a6 100644 --- a/src/qt/agrarian.cpp +++ b/src/qt/agrarian.cpp @@ -278,8 +278,9 @@ void BitcoinCore::restart(QStringList args) qDebug() << __func__ << ": Running Restart in thread"; Interrupt(); PrepareShutdown(); - qDebug() << __func__ << ": Shutdown finished"; emit shutdownResult(1); + QMetaObject::invokeMethod(QApplication::instance(), "quit", Qt::QueuedConnection); + QApplication::exit(0); CExplicitNetCleanup::callCleanup(); QProcess::startDetached(QApplication::applicationFilePath(), args); qDebug() << __func__ << ": Restart initiated..."; @@ -298,8 +299,9 @@ void BitcoinCore::shutdown() qDebug() << __func__ << ": Running Shutdown in thread"; Interrupt(); Shutdown(); - qDebug() << __func__ << ": Shutdown finished"; emit shutdownResult(1); + QMetaObject::invokeMethod(QApplication::instance(), "quit", Qt::QueuedConnection); + QApplication::exit(0); } catch (std::exception& e) { handleRunawayException(&e); } catch (...) { diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index f73b8cbc..dd0d7b48 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -8,6 +8,7 @@ #include "wallet/walletdb.h" #include "base58.h" +#include "init.h" #include "protocol.h" #include "serialize.h" #include "sync.h" @@ -916,7 +917,7 @@ void ThreadFlushWalletDB(const string& strFile) unsigned int nLastSeen = nWalletDBUpdated; unsigned int nLastFlushed = nWalletDBUpdated; int64_t nLastWalletUpdate = GetTime(); - while (true) { + while (!ShutdownRequested()) { MilliSleep(500); if (nLastSeen != nWalletDBUpdated) {