From fbd860287e6474bd7a61013796541bf2ea72d5cd Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Fri, 15 Feb 2013 14:10:01 -0500 Subject: [PATCH 1/3] Pass compiler flags down into leveldb make Fixes issue#2288. Includes cleanups from Luke's pull 2243. --- bitcoin-qt.pro | 4 ++-- contrib/gitian-descriptors/gitian-win32.yml | 2 +- src/makefile.linux-mingw | 15 +++++++++------ src/makefile.mingw | 15 ++++++++------- src/makefile.osx | 7 ++++--- src/makefile.unix | 6 ++++-- 6 files changed, 28 insertions(+), 21 deletions(-) diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 7bab4a4975b35..169d227794582 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -99,14 +99,14 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) { INCLUDEPATH += src/leveldb/include src/leveldb/helpers LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a !win32 { - genleveldb.commands = cd $$PWD/src/leveldb && $(MAKE) libleveldb.a libmemenv.a + genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) OPT=\"$$QMAKE_CXXFLAGS\" libleveldb.a libmemenv.a } else { # make an educated guess about what the ranlib command is called isEmpty(QMAKE_RANLIB) { QMAKE_RANLIB = $$replace(QMAKE_STRIP, strip, ranlib) } LIBS += -lshlwapi - genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a + genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) OPT=\"$$QMAKE_CXXFLAGS\" libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a } genleveldb.target = $$PWD/src/leveldb/libleveldb.a genleveldb.depends = FORCE diff --git a/contrib/gitian-descriptors/gitian-win32.yml b/contrib/gitian-descriptors/gitian-win32.yml index 9df42a0becf41..4860a159976b9 100644 --- a/contrib/gitian-descriptors/gitian-win32.yml +++ b/contrib/gitian-descriptors/gitian-win32.yml @@ -51,7 +51,7 @@ script: | export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME export TZ=UTC - $HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_50_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_50_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1c OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1c/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1 + $HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_50_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_50_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1c OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1c/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1 make $MAKEOPTS cp release/bitcoin-qt.exe $OUTDIR/ # diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index c3cbe90bcd5bd..f6c3a8ad7ee09 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -4,6 +4,9 @@ DEPSDIR:=/usr/i586-mingw32msvc +CC ?= i586-mingw32msvc-gcc +CXX ?= i586-mingw32msvc-g++ + USE_UPNP:=0 USE_IPV6:=1 @@ -58,6 +61,7 @@ LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l w HEADERS = $(wildcard *.h) OBJS= \ + leveldb/libleveldb.a \ obj/alert.o \ obj/version.o \ obj/checkpoints.o \ @@ -95,8 +99,7 @@ all: bitcoind.exe DEFS += -I"$(CURDIR)/leveldb/include" DEFS += -I"$(CURDIR)/leveldb/helpers" leveldb/libleveldb.a: - @echo "Building LevelDB ..." && cd leveldb && CC=i586-mingw32msvc-gcc CXX=i586-mingw32msvc-g++ TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="$(INCLUDEPATHS)" LDFLAGS="$(LIBPATHS)" $(MAKE) libleveldb.a libmemenv.a && i586-mingw32msvc-ranlib libleveldb.a && i586-mingw32msvc-ranlib libmemenv.a && cd .. -obj/leveldb.o: leveldb/libleveldb.a + @echo "Building LevelDB ..." && cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(CFLAGS)" libleveldb.a libmemenv.a && i586-mingw32msvc-ranlib libleveldb.a && i586-mingw32msvc-ranlib libmemenv.a && cd .. obj/build.h: FORCE /bin/sh ../share/genbuild.sh obj/build.h @@ -104,18 +107,18 @@ version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO obj/%.o: %.cpp $(HEADERS) - i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $< + $(CXX) -c $(CFLAGS) -o $@ $< bitcoind.exe: $(OBJS:obj/%=obj/%) - i586-mingw32msvc-g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) + $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) obj-test/%.o: test/%.cpp $(HEADERS) - i586-mingw32msvc-g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $< + $(CXX) -c $(TESTDEFS) $(CFLAGS) -o $@ $< test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%)) - i586-mingw32msvc-g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS) + $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS) clean: diff --git a/src/makefile.mingw b/src/makefile.mingw index 366d32bd86e6c..2e092ff6863d2 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -15,6 +15,8 @@ # 'make clean' assumes it is running inside a MSYS shell, and uses 'rm' # to remove files. +CXX ?= g++ + USE_UPNP:=- USE_IPV6:=1 @@ -67,6 +69,7 @@ LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell HEADERS = $(wildcard *.h) OBJS= \ + leveldb/libleveldb.a \ obj/alert.o \ obj/version.o \ obj/checkpoints.o \ @@ -112,23 +115,21 @@ DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) leveldb/libleveldb.a: - cd leveldb && $(MAKE) OPT="$(DEBUGFLAGS)" TARGET_OS=NATIVE_WINDOWS libleveldb.a libmemenv.a && cd .. - -obj/leveldb.o: leveldb/libleveldb.a + cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(CFLAGS)" TARGET_OS=NATIVE_WINDOWS libleveldb.a libmemenv.a && cd .. obj/%.o: %.cpp $(HEADERS) - g++ -c $(CFLAGS) -o $@ $< + $(CXX) -c $(CFLAGS) -o $@ $< bitcoind.exe: $(OBJS:obj/%=obj/%) - g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) + $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) obj-test/%.o: test/%.cpp $(HEADERS) - g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $< + $(CXX) -c $(TESTDEFS) $(CFLAGS) -o $@ $< test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%)) - g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework$(BOOST_SUFFIX) $(LIBS) + $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework$(BOOST_SUFFIX) $(LIBS) clean: rm -f bitcoind.exe test_bitcoin.exe diff --git a/src/makefile.osx b/src/makefile.osx index 8b7c559fa11da..cdee7812575fc 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -62,7 +62,7 @@ ifdef RELEASE # the same way. CFLAGS = -mmacosx-version-min=10.5 -arch i386 -O3 else -CFLAGS = -g +DEBUGFLAGS = -g endif # ppc doesn't work because we don't support big-endian @@ -70,6 +70,7 @@ CFLAGS += -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \ $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) OBJS= \ + leveldb/libleveldb.a \ obj/alert.o \ obj/version.o \ obj/checkpoints.o \ @@ -130,8 +131,7 @@ LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) leveldb/libleveldb.a: - @echo "Building LevelDB ..." && cd leveldb && $(MAKE) libleveldb.a libmemenv.a && cd .. -obj/leveldb.o: leveldb/libleveldb.a + @echo "Building LevelDB ..." && cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(CFLAGS)" libleveldb.a libmemenv.a && cd .. # auto-generated dependencies: -include obj/*.P @@ -171,5 +171,6 @@ clean: -rm -f obj/*.P -rm -f obj-test/*.P -rm -f obj/build.h + -cd leveldb && $(MAKE) clean || true FORCE: diff --git a/src/makefile.unix b/src/makefile.unix index b52a0f8aea1bd..ece2f59cf5a70 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -101,6 +101,7 @@ xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-para xLDFLAGS=$(LDHARDENING) $(LDFLAGS) OBJS= \ + leveldb/libleveldb.a \ obj/alert.o \ obj/version.o \ obj/checkpoints.o \ @@ -142,12 +143,12 @@ test check: test_bitcoin FORCE # # LevelDB support # +MAKEOVERRIDES = LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) leveldb/libleveldb.a: - @echo "Building LevelDB ..." && cd leveldb && $(MAKE) libleveldb.a libmemenv.a && cd .. -obj/leveldb.o: leveldb/libleveldb.a + @echo "Building LevelDB ..." && cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && cd .. # auto-generated dependencies: -include obj/*.P @@ -187,5 +188,6 @@ clean: -rm -f obj/*.P -rm -f obj-test/*.P -rm -f obj/build.h + -cd leveldb && $(MAKE) clean || true FORCE: From efb6d9aae7595ee2c76aa898b94aed53f079390f Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Fri, 15 Feb 2013 16:53:50 -0500 Subject: [PATCH 2/3] Minor build fixes Two changes: make some linux-specific linker options linux and linker specific. And in the cross-compile environment, prefer the $HOME/qt/bin tools to whatever might be somewhere else in the path. --- bitcoin-qt.pro | 16 ++++++++-------- contrib/gitian-descriptors/gitian-win32.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 169d227794582..1c6bc0a654304 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -29,19 +29,19 @@ contains(RELEASE, 1) { !win32:!macx { # Linux: static link - LIBS += -Wl,-Bstatic + LIBS += -Wl,-Bstatic -Wl,-z,relro -Wl,-z,now + # for extra security (see: https://wiki.debian.org/Hardening) + QMAKE_CXXFLAGS *= -D_FORTIFY_SOURCE=2 } } !win32 { -# for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection -QMAKE_CXXFLAGS *= -fstack-protector-all -QMAKE_LFLAGS *= -fstack-protector-all -# We need to exclude this for Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable! -# This can be enabled for Windows, when we switch to MinGW >= 4.4.x. + # for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection + QMAKE_CXXFLAGS *= -fstack-protector-all + QMAKE_LFLAGS *= -fstack-protector-all + # Exclude on Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable! + # This can be enabled for Windows, when we switch to MinGW >= 4.4.x. } -# for extra security (see: https://wiki.debian.org/Hardening) -QMAKE_CXXFLAGS *= -D_FORTIFY_SOURCE=2 -Wl,-z,relro -Wl,-z,now # for extra security on Windows: enable ASLR and DEP via GCC linker flags win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat # on Windows: enable GCC large address aware linker flag diff --git a/contrib/gitian-descriptors/gitian-win32.yml b/contrib/gitian-descriptors/gitian-win32.yml index 4860a159976b9..fd3b55325aebd 100644 --- a/contrib/gitian-descriptors/gitian-win32.yml +++ b/contrib/gitian-descriptors/gitian-win32.yml @@ -24,7 +24,7 @@ script: | cd $HOME/qt unzip ../build/qt-win32-4.8.3-gitian-r1.zip cd $HOME/build/ - export PATH=$PATH:$HOME/qt/bin/ + export PATH=$HOME/qt/bin/:$PATH # mkdir boost_1_50_0 cd boost_1_50_0 From 398774181a2d5575a0605e918944d85c5425d12e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 16 Feb 2013 17:58:45 +0100 Subject: [PATCH 3/3] Improve block database load error reporting --- src/init.cpp | 79 +++++++++++++++++++++++++++++++++---------- src/main.cpp | 12 +++++++ src/main.h | 2 ++ src/noui.cpp | 4 +-- src/qt/bitcoin.cpp | 8 +++-- src/qt/bitcoingui.cpp | 6 ++-- src/qt/bitcoingui.h | 3 +- src/ui_interface.h | 2 +- 8 files changed, 90 insertions(+), 26 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 15a46946fa665..99e89d9edc59f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -82,6 +82,7 @@ void Shutdown(void* parg) if (fFirstThread) { fShutdown = true; + fRequestShutdown = true; nTransactionsUpdated++; bitdb.Flush(false); { @@ -791,27 +792,69 @@ bool AppInit2() nTotalCache -= nCoinDBCache; nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes - uiInterface.InitMessage(_("Loading block index...")); + bool fLoaded = false; + while (!fLoaded) { + bool fReset = fReindex; + std::string strLoadError; - nStart = GetTimeMillis(); - pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); - pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); - pcoinsTip = new CCoinsViewCache(*pcoinsdbview); - - if (fReindex) - pblocktree->WriteReindexing(true); - - if (!LoadBlockIndex()) - return InitError(_("Error loading block database")); + uiInterface.InitMessage(_("Loading block index...")); - // Initialize the block index (no-op if non-empty database was already loaded) - if (!InitBlockIndex()) - return InitError(_("Error initializing block database")); - - uiInterface.InitMessage(_("Verifying block database integrity...")); + nStart = GetTimeMillis(); + do { + try { + UnloadBlockIndex(); + delete pcoinsTip; + delete pcoinsdbview; + delete pblocktree; + + pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); + pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); + pcoinsTip = new CCoinsViewCache(*pcoinsdbview); + + if (fReindex) + pblocktree->WriteReindexing(true); + + if (!LoadBlockIndex()) { + strLoadError = _("Error loading block database"); + break; + } + + // Initialize the block index (no-op if non-empty database was already loaded) + if (!InitBlockIndex()) { + strLoadError = _("Error initializing block database"); + break; + } + + uiInterface.InitMessage(_("Verifying block database integrity...")); + if (!VerifyDB()) { + strLoadError = _("Corrupted block database detected"); + break; + } + } catch(std::exception &e) { + strLoadError = _("Error opening block database"); + break; + } - if (!VerifyDB()) - return InitError(_("Corrupted block database detected. Please restart the client with -reindex.")); + fLoaded = true; + } while(false); + + if (!fLoaded) { + // first suggest a reindex + if (!fReset) { + bool fRet = uiInterface.ThreadSafeMessageBox( + strLoadError + ".\n" + _("Do you want to rebuild the block database now?"), + "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); + if (fRet) { + fReindex = true; + fRequestShutdown = false; + } else { + return false; + } + } else { + return InitError(strLoadError); + } + } + } if (mapArgs.count("-txindex") && fTxIndex != GetBoolArg("-txindex", false)) return InitError(_("You need to rebuild the databases using -reindex to change -txindex")); diff --git a/src/main.cpp b/src/main.cpp index 8c115c26f96be..3151a806dcb23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2653,6 +2653,18 @@ bool VerifyDB() { return true; } +void UnloadBlockIndex() +{ + mapBlockIndex.clear(); + setBlockIndexValid.clear(); + pindexGenesisBlock = NULL; + nBestHeight = 0; + bnBestChainWork = 0; + bnBestInvalidWork = 0; + hashBestChain = 0; + pindexBest = NULL; +} + bool LoadBlockIndex() { if (fTestNet) diff --git a/src/main.h b/src/main.h index d69aef94eaa91..4a217d174605c 100644 --- a/src/main.h +++ b/src/main.h @@ -139,6 +139,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); bool InitBlockIndex(); /** Load the block tree and coins database from disk */ bool LoadBlockIndex(); +/** Unload database information */ +void UnloadBlockIndex(); /** Verify consistency of the block and coin databases */ bool VerifyDB(); /** Print the loaded block tree */ diff --git a/src/noui.cpp b/src/noui.cpp index 302d05929121a..c0e00c471553f 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -9,7 +9,7 @@ #include -static int noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) +static bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) { std::string strCaption; // Check for usage of predefined caption @@ -29,7 +29,7 @@ static int noui_ThreadSafeMessageBox(const std::string& message, const std::stri printf("%s: %s\n", strCaption.c_str(), message.c_str()); fprintf(stderr, "%s: %s\n", strCaption.c_str(), message.c_str()); - return 4; + return false; } static bool noui_ThreadSafeAskFee(int64 /*nFeeRequired*/) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index e5526a6c09ba4..afd8d71a0eca0 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -34,23 +34,27 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets) static BitcoinGUI *guiref; static QSplashScreen *splashref; -static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) +static bool ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) { // Message from network thread if(guiref) { bool modal = (style & CClientUIInterface::MODAL); + bool ret = false; // In case of modal message, use blocking connection to wait for user to click a button QMetaObject::invokeMethod(guiref, "message", modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(caption)), Q_ARG(QString, QString::fromStdString(message)), - Q_ARG(unsigned int, style)); + Q_ARG(unsigned int, style), + Q_ARG(bool*, &ret)); + return ret; } else { printf("%s: %s\n", caption.c_str(), message.c_str()); fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); + return false; } } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 9cd22ed297679..d88470188381a 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -606,7 +606,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) progressBar->setToolTip(tooltip); } -void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style) +void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret) { QString strTitle = tr("Bitcoin") + " - "; // Default to information icon @@ -646,7 +646,9 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned buttons = QMessageBox::Ok; QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons); - mBox.exec(); + int r = mBox.exec(); + if (ret != NULL) + *ret = r == QMessageBox::Ok; } else notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index b7afdb1c8c610..c684fcf249537 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -126,8 +126,9 @@ public slots: @param[in] message the displayed text @param[in] style modality and style definitions (icon and used buttons - buttons only for message boxes) @see CClientUIInterface::MessageBoxFlags + @param[in] ret pointer to a bool that will be modified to whether Ok was clicked (modal only) */ - void message(const QString &title, const QString &message, unsigned int style); + void message(const QString &title, const QString &message, unsigned int style, bool *ret = NULL); /** Asks the user whether to pay the transaction fee or to cancel the transaction. It is currently not possible to pass a return value to another thread through BlockingQueuedConnection, so an indirected pointer is used. diff --git a/src/ui_interface.h b/src/ui_interface.h index 703e15f0957f6..f7dbe208944e5 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -68,7 +68,7 @@ class CClientUIInterface }; /** Show message box. */ - boost::signals2::signal ThreadSafeMessageBox; + boost::signals2::signal > ThreadSafeMessageBox; /** Ask the user whether they want to pay a fee or not. */ boost::signals2::signal > ThreadSafeAskFee;