summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2012-03-15 23:35:19 -0400
committerNat Goodspeed <nat@lindenlab.com>2012-03-15 23:35:19 -0400
commitcf39274b640e983a5fcc2d03e4c47947a2b36732 (patch)
tree2a20437a61c223642234b9d2f61408c1ae37718b
parent4edf34ed01611d75bdcd98aa065a2b286845ebd9 (diff)
Make LLLeap intercept LL_ERRS termination and notify LEAP plugin.
Have to pump "mainloop" a few times to flush the buffer to the pipe, a potentially risky strategy: we have to trust that whatever condition led to the LL_ERRS fatal error didn't break anything that listens on "mainloop". But the worst that could happen is that the plugin won't be notified -- just as if we didn't try in the first place. In other words, no harm in trying.
-rw-r--r--indra/llcommon/llleap.cpp36
1 files changed, 35 insertions, 1 deletions
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 034c809330..07880bd818 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -29,12 +29,15 @@
#include "stringize.h"
#include "llsdutil.h"
#include "llsdserialize.h"
+#include "llerrorcontrol.h"
+#include "lltimer.h"
LLLeap::LLLeap() {}
LLLeap::~LLLeap() {}
class LLLeapImpl: public LLLeap
{
+ LOG_CLASS(LLLeap);
public:
// Called only by LLLeap::create()
LLLeapImpl(const std::string& desc, const std::vector<std::string>& plugin):
@@ -48,7 +51,8 @@ public:
// Try to make that more difficult by generating a UUID for the reply-
// pump name -- so it should NOT need tweaking for uniqueness.
mReplyPump(LLUUID::generateNewID().asString()),
- mExpect(0)
+ mExpect(0),
+ mPrevFatalFunction(LLError::getFatalFunction())
{
// Rule out empty vector
if (plugin.empty())
@@ -135,6 +139,9 @@ public:
mStderrConnection = childerr.getPump()
.listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
+ // For our lifespan, intercept any LL_ERRS so we can notify plugin
+ LLError::setFatalFunction(boost::bind(&LLLeapImpl::fatalFunction, this, _1));
+
// Send child a preliminary event reporting our own reply-pump name --
// which would otherwise be pretty tricky to guess!
// TODO TODO inject name of command pump here.
@@ -150,6 +157,8 @@ public:
virtual ~LLLeapImpl()
{
LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
+ // Restore original FatalFunction
+ LLError::setFatalFunction(mPrevFatalFunction);
}
// Listener for failed launch attempt
@@ -363,6 +372,30 @@ public:
return false;
}
+ void fatalFunction(const std::string& error)
+ {
+ // Notify plugin
+ LLSD event;
+ event["type"] = "error";
+ event["error"] = error;
+ mReplyPump.post(event);
+
+ // All the above really accomplished was to buffer the serialized
+ // event in our WritePipe. Have to pump mainloop a couple times to
+ // really write it out there... but time out in case we can't write.
+ LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+ LLSD nop;
+ F64 until(LLTimer::getElapsedSeconds() + 2);
+ while (childin.size() && LLTimer::getElapsedSeconds() < until)
+ {
+ mainloop.post(nop);
+ }
+
+ // forward the call to the previous FatalFunction
+ mPrevFatalFunction(error);
+ }
+
private:
std::string mDesc;
LLEventStream mDonePump;
@@ -372,6 +405,7 @@ private:
mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
boost::scoped_ptr<LLEventPump::Blocker> mBlocker;
LLProcess::ReadPipe::size_type mExpect;
+ LLError::FatalFunction mPrevFatalFunction;
};
// This must follow the declaration of LLLeapImpl, so it may as well be last.