From: Wladimir J. van der Laan Date: Thu, 18 Aug 2016 14:58:04 +0000 (+0200) Subject: qt: Fix random segfault when closing "Choose data directory" dialog X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=7ecd4c94433c6233faaf8f6fb6eb89df23ee4f4b qt: Fix random segfault when closing "Choose data directory" dialog The `pickDataDirectory()` function was calling `exit(0)` to quit the application when the user closes the dialog without choosing a data directory. This is a bad idea because a background thread is created (to check free space on the drive of the currently selected datadir). The thread is not stopped and unwound properly, resulting in a potential race condition somewhere deep in Qt. So replace the `exit()` by a boolean return value, and let the stack unwind normally. --- diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index f99ee0f..7e73504 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -176,7 +176,8 @@ int main(int argc, char *argv[]) ParseParameters(argc, argv); // User language is set up: pick a data directory - Intro::pickDataDirectory(); + if (!Intro::pickDataDirectory()) + return 0; // Install global event filter that makes sure that long tooltips can be word-wrapped app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app)); diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 75c1c82..6da9833 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -149,14 +149,14 @@ QString Intro::getDefaultDataDirectory() return GUIUtil::boostPathToQString(GetDefaultDataDir()); } -void Intro::pickDataDirectory() +bool Intro::pickDataDirectory() { namespace fs = boost::filesystem; QSettings settings; /* If data directory provided on command line, no need to look at settings or show a picking dialog */ if(!GetArg("-datadir", "").empty()) - return; + return true; /* 1) Default data directory for operating system */ QString dataDir = getDefaultDataDirectory(); /* 2) Allow QSettings to override default dir */ @@ -174,7 +174,7 @@ void Intro::pickDataDirectory() if(!intro.exec()) { /* Cancel clicked */ - exit(0); + return false; } dataDir = intro.getDataDirectory(); try { @@ -195,6 +195,7 @@ void Intro::pickDataDirectory() */ if(dataDir != getDefaultDataDirectory()) SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting + return true; } void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable) diff --git a/src/qt/intro.h b/src/qt/intro.h index c973561..dd9eb5b 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -33,10 +33,13 @@ public: /** * Determine data directory. Let the user choose if the current one doesn't exist. * + * @returns true if a data directory was selected, false if the user cancelled the selection + * dialog. + * * @note do NOT call global GetDataDir() before calling this function, this * will cause the wrong path to be cached. */ - static void pickDataDirectory(); + static bool pickDataDirectory(); /** * Determine default data directory for operating system.