summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2018-10-03 14:00:05 -0400
committerNat Goodspeed <nat@lindenlab.com>2018-10-03 14:00:05 -0400
commitb1955d4247a4d28a3a4c259036390ff632e80008 (patch)
tree3cc4f620431c4cef25dd880e1ff391ada1a2c93b
parent6e1b2e137e2b6c6d92d14f478b6908c0c2f1e231 (diff)
DRTVWR-474: Do NOT autokill updater process on viewer termination.
The updater is required to survive beyond termination of the viewer that launched it so it can launch the next installer, or a replacement viewer. Having the old viewer forcibly terminate it on shutdown would be counter- productive. Introduce a third LLLeap::create() overload taking LLProcess::Params, which gives access to autokill, cwd and other options previously unsupported by LLLeap. Reimplement the existing create() overloads in terms of this new one, since LLLeapImpl::LLLeapImpl() is already based on LLProcess::Params anyway. Use LLProcess::Params in LLAppViewer::init() to specify the updater process, setting autokill=false. Refactoring LLLeapImpl() apparently involved engaging an LLInitParam::Block feature never before used: had to drag operator() into Multiple from its base class TypedParam (as has been done in other TypedParam subclasses).
-rw-r--r--indra/llcommon/llinitparam.h3
-rw-r--r--indra/llcommon/llleap.cpp51
-rw-r--r--indra/llcommon/llleap.h14
-rw-r--r--indra/newview/llappviewer.cpp33
4 files changed, 65 insertions, 36 deletions
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index f1f4226c40..7f5b9b4ac2 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -2115,6 +2115,9 @@ namespace LLInitParam
typedef typename super_t::iterator iterator;
typedef typename super_t::const_iterator const_iterator;
+ using super_t::operator();
+ using super_t::operator const container_t&;
+
explicit Multiple(const char* name = "")
: super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
{}
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index c87d2a3e58..cf8f8cc6a5 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -47,9 +47,9 @@ class LLLeapImpl: public LLLeap
LOG_CLASS(LLLeap);
public:
// Called only by LLLeap::create()
- LLLeapImpl(const std::string& desc, const std::vector<std::string>& plugin):
+ LLLeapImpl(const LLProcess::Params& cparams):
// We might reassign mDesc in the constructor body if it's empty here.
- mDesc(desc),
+ mDesc(cparams.desc),
// We expect multiple LLLeapImpl instances. Definitely tweak
// mDonePump's name for uniqueness.
mDonePump("LLLeap", true),
@@ -67,17 +67,17 @@ public:
// this class or method name.
mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2)))
{
- // Rule out empty vector
- if (plugin.empty())
+ // Rule out unpopulated Params block
+ if (! cparams.executable.isProvided())
{
LLTHROW(Error("no plugin command"));
}
// Don't leave desc empty either, but in this case, if we weren't
// given one, we'll fake one.
- if (desc.empty())
+ if (mDesc.empty())
{
- mDesc = LLProcess::basename(plugin[0]);
+ mDesc = LLProcess::basename(cparams.executable);
// how about a toLower() variant that returns the transformed string?!
std::string desclower(mDesc);
LLStringUtil::toLower(desclower);
@@ -87,9 +87,9 @@ public:
// notice Python specially: we provide Python LLSD serialization
// support, so there's a pretty good reason to implement plugins
// in that language.
- if (plugin.size() >= 2 && (desclower == "python" || desclower == "python.exe"))
+ if (cparams.args.size() && (desclower == "python" || desclower == "python.exe"))
{
- mDesc = LLProcess::basename(plugin[1]);
+ mDesc = LLProcess::basename(cparams.args()[0]);
}
}
@@ -97,14 +97,10 @@ public:
mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::bad_launch, this, _1));
// Okay, launch child.
- LLProcess::Params params;
+ // Get a modifiable copy of params block to set files and postend.
+ LLProcess::Params params(cparams);
+ // copy our deduced mDesc back into the params block
params.desc = mDesc;
- std::vector<std::string>::const_iterator pi(plugin.begin()), pend(plugin.end());
- params.executable = *pi++;
- for ( ; pi != pend; ++pi)
- {
- params.args.add(*pi);
- }
params.files.add(LLProcess::FileParam("pipe")); // stdin
params.files.add(LLProcess::FileParam("pipe")); // stdout
params.files.add(LLProcess::FileParam("pipe")); // stderr
@@ -429,17 +425,17 @@ private:
boost::scoped_ptr<LLLeapListener> mListener;
};
-// This must follow the declaration of LLLeapImpl, so it may as well be last.
-LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>& plugin, bool exc)
+// These must follow the declaration of LLLeapImpl, so they may as well be last.
+LLLeap* LLLeap::create(const LLProcess::Params& params, bool exc)
{
// If caller is willing to permit exceptions, just instantiate.
if (exc)
- return new LLLeapImpl(desc, plugin);
+ return new LLLeapImpl(params);
// Caller insists on suppressing LLLeap::Error. Very well, catch it.
try
{
- return new LLLeapImpl(desc, plugin);
+ return new LLLeapImpl(params);
}
catch (const LLLeap::Error&)
{
@@ -447,6 +443,23 @@ LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>&
}
}
+LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>& plugin, bool exc)
+{
+ LLProcess::Params params;
+ params.desc = desc;
+ std::vector<std::string>::const_iterator pi(plugin.begin()), pend(plugin.end());
+ // could validate here, but let's rely on LLLeapImpl's constructor
+ if (pi != pend)
+ {
+ params.executable = *pi++;
+ }
+ for ( ; pi != pend; ++pi)
+ {
+ params.args.add(*pi);
+ }
+ return create(params, exc);
+}
+
LLLeap* LLLeap::create(const std::string& desc, const std::string& plugin, bool exc)
{
// Use LLStringUtil::getTokens() to parse the command line
diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h
index 8aac8a64c5..7cecdf2f8f 100644
--- a/indra/llcommon/llleap.h
+++ b/indra/llcommon/llleap.h
@@ -14,6 +14,7 @@
#include "llinstancetracker.h"
#include "llexception.h"
+#include "llprocess.h"
#include <string>
#include <vector>
@@ -62,6 +63,19 @@ public:
bool exc=true);
/**
+ * Pass an LLProcess::Params instance to specify desc, executable, args et al.
+ *
+ * Note that files and postend are set implicitly; any values you set in
+ * those fields will be disregarded.
+ *
+ * Pass exc=false to suppress LLLeap::Error exception. Obviously in that
+ * case the caller cannot discover the nature of the error, merely that an
+ * error of some kind occurred (because create() returned NULL). Either
+ * way, the error is logged.
+ */
+ static LLLeap* create(const LLProcess::Params& params, bool exc=true);
+
+ /**
* Exception thrown for invalid create() arguments, e.g. no plugin
* program. This is more resiliant than an LL_ERRS failure, because the
* string(s) passed to create() might come from an external source. This
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 776fc85a2d..bc4ce19f77 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1130,30 +1130,35 @@ bool LLAppViewer::init()
gGLActive = FALSE;
- std::vector<std::string> updater
+ LLProcess::Params updater;
+ updater.desc = "updater process";
+ // Because it's the updater, it MUST persist beyond the lifespan of the
+ // viewer itself.
+ updater.autokill = false;
#if LL_WINDOWS
- { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe") };
+ updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe");
#elif LL_DARWIN
// explicitly run the system Python interpreter on updater.py
- { "python", gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py") };
+ updater.executable = "python";
+ updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py"));
#else
- { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater") };
+ updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater");
#endif
// add LEAP mode command-line argument to whichever of these we selected
- updater.push_back("leap");
+ updater.args.add("leap");
// UpdaterServiceSettings
- updater.push_back(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
+ updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
// channel
- updater.push_back(LLVersionInfo::getChannel());
+ updater.args.add(LLVersionInfo::getChannel());
// testok
- updater.push_back(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
+ updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
// UpdaterServiceURL
- updater.push_back(gSavedSettings.getString("UpdaterServiceURL"));
+ updater.args.add(gSavedSettings.getString("UpdaterServiceURL"));
// ForceAddressSize
- updater.push_back(stringize(gSavedSettings.getU32("ForceAddressSize")));
+ updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
// Run the updater. An exception from launching the updater should bother us.
- LLLeap::create("updater process", updater, true);
+ LLLeap::create(updater, true);
// Iterate over --leap command-line options. But this is a bit tricky: if
// there's only one, it won't be an array at all.
@@ -3923,12 +3928,6 @@ void LLAppViewer::requestQuit()
gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
}
- // Try to send last batch of avatar rez metrics.
- if (!gDisconnected && isAgentAvatarValid())
- {
- gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
- }
-
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
effectp->setPositionGlobal(gAgent.getPositionGlobal());
effectp->setColor(LLColor4U(gAgent.getEffectColor()));