From 4ac8523bedce841bd1b4ff553757071fe6ccf1b3 Mon Sep 17 00:00:00 2001
From: Automatic Release Builder <build@flightgear.org>
Date: Tue, 6 Oct 2020 11:56:58 +0100
Subject: [PATCH] SetupRootDialog: avoid calling exit()

This causes QApplication to become unhappy and crash, so use a
graceful exit via a new return code and FG_OPTIONS_EXIT instead.

Sentry-Id: FLIGHTGEAR-6B
---
 src/GUI/SetupRootDialog.cxx | 51 +++++++++++++++++++------------------
 src/GUI/SetupRootDialog.hxx | 11 ++++++--
 src/Main/options.cxx        |  8 +++++-
 3 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/GUI/SetupRootDialog.cxx b/src/GUI/SetupRootDialog.cxx
index cc9ecb525..2c42a0dea 100755
--- a/src/GUI/SetupRootDialog.cxx
+++ b/src/GUI/SetupRootDialog.cxx
@@ -96,7 +96,7 @@ bool SetupRootDialog::runDialog(PromptState prompt)
 }
 
 
-SGPath SetupRootDialog::restoreUserSelectedRoot()
+SetupRootDialog::RestoreResult SetupRootDialog::restoreUserSelectedRoot(SGPath& sgpath)
 {
     QSettings settings;
     QString path = settings.value(rootPathKey()).toString();
@@ -104,39 +104,40 @@ SGPath SetupRootDialog::restoreUserSelectedRoot()
     if (ask || (path == QStringLiteral("!ask"))) {
         bool ok = runDialog(ManualChoiceRequested);
         if (!ok) {
-            exit(-1);
+            return UserExit;
         }
 
-        // run dialog either exit()s or sets fg_root, so this
-        // behaviour is safe and correct.
-        return globals->get_fg_root();
+        sgpath = globals->get_fg_root();
+        return UserSelected;
     }
 
     if (path.isEmpty()) {
-        return SGPath{}; // use the default path
+        return UseDefault;
     }
 
     if (validatePath(path) && validateVersion(path)) {
-        return SGPath::fromUtf8(path.toStdString());
-    } else {
-        // we have an existing path but it's invalid.
-        // let's see if the default root is acceptable, in which case we will
-        // switch to it. (This gives a more friendly upgrade experience).
-        if (defaultRootAcceptable()) {
-            return SGPath{}; // use the default path
-        }
-
-        // okay, we don't have an acceptable FG_DATA anywhere we can find, we
-        // have to ask the user what they want to do.
-        bool ok = runDialog(VersionCheckFailed);
-        if (!ok) {
-            exit(-1);
-        }
-
-        // run dialog either exit()s or sets fg_root, so this
-        // behaviour is safe and correct.
-        return globals->get_fg_root();
+        sgpath = SGPath::fromUtf8(path.toStdString());
+        return RestoredOk;
     }
+
+    // we have an existing path but it's invalid.
+    // let's see if the default root is acceptable, in which case we will
+    // switch to it. (This gives a more friendly upgrade experience).
+    if (defaultRootAcceptable()) {
+        return UseDefault;
+    }
+
+    // okay, we don't have an acceptable FG_DATA anywhere we can find, we
+    // have to ask the user what they want to do.
+    bool ok = runDialog(VersionCheckFailed);
+    if (!ok) {
+        return UserExit;
+    }
+
+    // run dialog sets fg_root, so this
+    // behaviour is safe and correct.
+    sgpath = globals->get_fg_root();
+    return UserSelected;
 }
 
 void SetupRootDialog::askRootOnNextLaunch()
diff --git a/src/GUI/SetupRootDialog.hxx b/src/GUI/SetupRootDialog.hxx
index 79f758e3f..6cb805f9c 100644
--- a/src/GUI/SetupRootDialog.hxx
+++ b/src/GUI/SetupRootDialog.hxx
@@ -40,8 +40,15 @@ public:
 
     static bool runDialog(bool usingDefaultRoot);
 
-    static SGPath restoreUserSelectedRoot();
-    
+    enum RestoreResult {
+        RestoredOk,
+        UserExit,
+        UserSelected,
+        UseDefault
+    };
+
+    static RestoreResult restoreUserSelectedRoot(SGPath& path);
+
     static void askRootOnNextLaunch();
     
     static QString rootPathKey();
diff --git a/src/Main/options.cxx b/src/Main/options.cxx
index f9e30ac0e..7a648e380 100644
--- a/src/Main/options.cxx
+++ b/src/Main/options.cxx
@@ -2992,8 +2992,14 @@ OptionResult Options::setupRoot(int argc, char** argv)
         SG_LOG(SG_GENERAL, SG_INFO, "set from FG_ROOT env var: fg_root = " << root );
     } else {
 #if defined(HAVE_QT)
-        root = SetupRootDialog::restoreUserSelectedRoot();
+        auto restoreResult = SetupRootDialog::restoreUserSelectedRoot(root);
+        if (restoreResult == SetupRootDialog::UserExit) {
+            return FG_OPTIONS_EXIT;
+        } else if (restoreResult == SetupRootDialog::UseDefault) {
+            root = SGPath{}; // clear any value, so we fall through in root.isNull() below
+        }
 #endif
+
         if (root.isNull()) {
             usingDefaultRoot = true;
             root = platformDefaultRoot();