From 27cadfbe951abb2cf350d5a1c91876ac958d50cf Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 17 Oct 2009 12:21:22 -0400
Subject: [PATCH] DEV-40930: Introduce LLAppViewerListener "forceQuit"
 operation. The bug was driven by the following sequence in llstartup.cpp:    
         if(reason_response == "update"                 || reason_response ==
 "optional")             {                 // used to resend status event
 still containing "update",                 // erroneously instantiating a
 second forced-update                 // LLAlertDialog                
 LLLoginInstance::getInstance()->disconnect();                 // quit with an
 LLAlertDialog still on sModalStack used                 // to result in
 LL_ERRS                 LLAppViewer::instance()->forceQuit();             } I
 hope to be able to introduce a test script to verify the fix. That script
 would need to be able to call LLAppViewer::forceQuit() rather than
 requestQuit(), which is already available via LLAppViewerListener.

At the same time, changed LLAppViewerListener to bind a functor to
retrieve an LLAppViewer instance (namely LLAppViewer::instance) rather
than an LLAppViewer*. Apparently the static instantiation of
LLAppViewerListener was calling LLAppViewer::instance() too early, before
things were ready, so the declaration was changed to pass NULL -- then
in each method, call LLAppViewer::instance() if the bound pointer is NULL.
Binding the LLAppViewer* is a Feathers tactic intended to avoid the need
to reference the singleton. Binding a functor still leaves it up to the
instantiating code to reference LLAppViewer::instance, while deferring
the actual call to that method.
---
 indra/newview/llappviewer.cpp         |  2 +-
 indra/newview/llappviewerlistener.cpp | 17 ++++++++++-------
 indra/newview/llappviewerlistener.h   |  7 +++++--
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a631314d5bf..80749295ffd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -204,7 +204,7 @@
 #pragma warning (disable:4702)
 #endif
 
-static LLAppViewerListener sAppViewerListener("LLAppViewer", NULL);
+static LLAppViewerListener sAppViewerListener("LLAppViewer", LLAppViewer::instance);
 
 ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
 //
diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp
index a3af251a3c3..3259309eee7 100644
--- a/indra/newview/llappviewerlistener.cpp
+++ b/indra/newview/llappviewerlistener.cpp
@@ -19,19 +19,22 @@
 // other Linden headers
 #include "llappviewer.h"
 
-LLAppViewerListener::LLAppViewerListener(const std::string& pumpname, LLAppViewer* llappviewer):
+LLAppViewerListener::LLAppViewerListener(const std::string& pumpname,
+                                         const LLAppViewerGetter& getter):
     LLDispatchListener(pumpname, "op"),
-    mAppViewer(llappviewer)
+    mAppViewerGetter(getter)
 {
     // add() every method we want to be able to invoke via this event API.
     add("requestQuit", &LLAppViewerListener::requestQuit);
+    add("forceQuit", &LLAppViewerListener::forceQuit);
 }
 
 void LLAppViewerListener::requestQuit(const LLSD& event)
 {
-    if(mAppViewer == NULL)
-    {
-        mAppViewer = LLAppViewer::instance();
-    }
-    mAppViewer->requestQuit();
+    mAppViewerGetter()->requestQuit();
+}
+
+void LLAppViewerListener::forceQuit(const LLSD& event)
+{
+    mAppViewerGetter()->forceQuit();
 }
diff --git a/indra/newview/llappviewerlistener.h b/indra/newview/llappviewerlistener.h
index d702f605ef0..73227cb95a7 100644
--- a/indra/newview/llappviewerlistener.h
+++ b/indra/newview/llappviewerlistener.h
@@ -13,6 +13,7 @@
 #define LL_LLAPPVIEWERLISTENER_H
 
 #include "lleventdispatcher.h"
+#include <boost/function.hpp>
 
 class LLAppViewer;
 class LLSD;
@@ -21,14 +22,16 @@ class LLSD;
 class LLAppViewerListener: public LLDispatchListener
 {
 public:
+    typedef boost::function<LLAppViewer*(void)> LLAppViewerGetter;
     /// Specify the pump name on which to listen, and bind the LLAppViewer
     /// instance to use (e.g. LLAppViewer::instance()).
-    LLAppViewerListener(const std::string& pumpname, LLAppViewer* llappviewer);
+    LLAppViewerListener(const std::string& pumpname, const LLAppViewerGetter& getter);
 
 private:
     void requestQuit(const LLSD& event);
+    void forceQuit(const LLSD& event);
 
-    LLAppViewer* mAppViewer;
+    LLAppViewerGetter mAppViewerGetter;
 };
 
 #endif /* ! defined(LL_LLAPPVIEWERLISTENER_H) */
-- 
GitLab