diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 0407d6c3e9..111ad4322e 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -38,7 +38,8 @@ LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown) { // Register for "LLApp" events so we can implicitly close() on viewer shutdown std::string listener_name = "WorkQueue:" + getKey(); - LLEventPumps::instance().obtain("LLApp").listen( + LLEventPumps* pump = LLEventPumps::getInstance(); + pump->obtain("LLApp").listen( listener_name, [this](const LLSD& stat) { @@ -54,14 +55,25 @@ LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown) // Store the listener name so we can unregister in the destructor mListenerName = listener_name; + mPumpHandle = pump->getHandle(); } } LL::WorkQueueBase::~WorkQueueBase() { - if (!mListenerName.empty() && !LLEventPumps::wasDeleted()) + if (!mListenerName.empty() && !mPumpHandle.isDead()) { - LLEventPumps::instance().obtain("LLApp").stopListening(mListenerName); + // Due to shutdown order issues, use handle, not a singleton + // and ignore fiber issue. + try + { + LLEventPumps* pump = mPumpHandle.get(); + pump->obtain("LLApp").stopListening(mListenerName); + } + catch (const boost::fibers::lock_error&) + { + // Likely mutex is down, ignore + } } } diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 573203a5b3..69f3286c1b 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -14,6 +14,7 @@ #include "llcoros.h" #include "llexception.h" +#include "llhandle.h" #include "llinstancetracker.h" #include "llinstancetrackersubclass.h" #include "threadsafeschedule.h" @@ -22,6 +23,9 @@ #include // std::function #include +class LLEventPumps; + + namespace LL { @@ -202,6 +206,8 @@ namespace LL // Name used for the LLApp event listener (empty if not registered) std::string mListenerName; + // Due to shutdown order issues, store by handle + LLHandle mPumpHandle; }; /***************************************************************************** diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 27995288e5..e5fbd06f69 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -388,7 +388,15 @@ const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker"); static std::string gLaunchFileOnQuit; // Used on Win32 for other apps to identify our window (eg, win_setup) +#if LL_VELOPACK +// Velopack is deliberately different fron NSIS to not prevent nsis uninstall +const char* const VIEWER_WINDOW_CLASSNAME = "Second\u00A0Life"; // no break space +#else +// NSIS relies on this to detect if viewer is up. +// NSIS's method is somewhat unreliable since window +// can close long before cleanup is done const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; +#endif //---------------------------------------------------------------------------- diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index a02311b74c..0aa2ae5023 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -435,6 +435,20 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, if (!velopack_initialize()) { // Velopack handled the invocation (install/uninstall hook) + + // Drop install related settings + gDirUtilp->initAppDirs("SecondLife"); + + std::string user_settings_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"); + LLControlGroup settings("global"); + if (settings.loadFromFile(user_settings_path)) + { + if (settings.controlExists("LastInstallVersion")) + { + settings.setString("LastInstallVersion", std::string()); + } + settings.saveToFile(user_settings_path, true); + } return 0; } #endif diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6f0c9c99df..d9de8ca1ca 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2619,18 +2619,25 @@ void release_notes_coro(const std::string url) void uninstall_nsis_if_required() { #if LL_VELOPACK && LL_WINDOWS - // Todo: perhaps use marker files? - // Debug variable isn't specific to one channel - // and something channel specific is needed. std::string last_install_ver = gSavedSettings.getString("LastInstallVersion"); - LLVersionInfo* ver_inst = LLVersionInfo::getInstance(); - if (ver_inst->getChannelAndVersion() == last_install_ver) + if (!last_install_ver.empty()) { return; } + LLVersionInfo* ver_inst = LLVersionInfo::getInstance(); gSavedSettings.setString("LastInstallVersion", ver_inst->getChannelAndVersion()); + if (LLNotifications::instance().getIgnored("PromptRemoveNsisInstallation")) + { + // By default 'ignore' returns default button, which is uninstall + // for PromptRemoveNsisInstallation, but while we want the button + // to be the default, we don't want a scary UAC without a notice + // as a default action, so if this notification is ignored, + // we will treat it as if user is going to cancel the uninstall. + return; + } + LL_INFOS() << "Looking for previous NSIS installs" << LL_ENDL; wchar_t buffer[MAX_PATH]; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 26ed49dfac..f282e934ff 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -209,7 +209,8 @@ No tutorial is currently available. The uninstaller may display additional prompts requesting permission to access or modify files on your disk. confirm