Fixes for a different class of plugin failures (where loading the plugin dll fails) causing an error message loop:
Made LLPluginProcessParent differentiate between failures launching/loading the plugin and failures after the plugin has been loaded. This allows us to handle launch failures differently, since retrying is unlikely to fix them. Added new media event MEDIA_EVENT_PLUGIN_FAILED_LAUNCH to indicate a launch failure. Added a case for the new event to LLViewerMediaImpl::handleMediaEvent() that sets the "failed init" flag to prevent retries.master
parent
0c47583399
commit
374deb8da1
|
|
@ -883,6 +883,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
|
|||
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void LLPluginClassMedia::pluginLaunchFailed()
|
||||
{
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void LLPluginClassMedia::pluginDied()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ public:
|
|||
|
||||
// Inherited from LLPluginProcessParentOwner
|
||||
/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
|
||||
/* virtual */ void pluginLaunchFailed();
|
||||
/* virtual */ void pluginDied();
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ public:
|
|||
MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are
|
||||
MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
|
||||
|
||||
MEDIA_EVENT_PLUGIN_FAILED // The plugin failed to launch or died unexpectedly
|
||||
MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
|
||||
MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly
|
||||
|
||||
} EMediaEvent;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,14 @@ void LLPluginProcessParent::killSockets(void)
|
|||
mSocket.reset();
|
||||
}
|
||||
|
||||
void LLPluginProcessParent::errorState(void)
|
||||
{
|
||||
if(mState < STATE_RUNNING)
|
||||
setState(STATE_LAUNCH_FAILURE);
|
||||
else
|
||||
setState(STATE_ERROR);
|
||||
}
|
||||
|
||||
void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename)
|
||||
{
|
||||
mProcess.setExecutable(launcher_filename);
|
||||
|
|
@ -132,7 +140,7 @@ bool LLPluginProcessParent::accept()
|
|||
ll_apr_warn_status(status);
|
||||
|
||||
// Some other error.
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -150,15 +158,15 @@ void LLPluginProcessParent::idle(void)
|
|||
if(!mMessagePipe->pump())
|
||||
{
|
||||
// LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL;
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
}
|
||||
|
||||
if((mSocketError != APR_SUCCESS) && (mState < STATE_ERROR))
|
||||
if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING))
|
||||
{
|
||||
// The socket is in an error state -- the plugin is gone.
|
||||
LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
|
||||
// If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
|
||||
|
|
@ -191,7 +199,7 @@ void LLPluginProcessParent::idle(void)
|
|||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +210,7 @@ void LLPluginProcessParent::idle(void)
|
|||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +220,7 @@ void LLPluginProcessParent::idle(void)
|
|||
if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
|
||||
{
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
mBoundPort = bound_addr->port;
|
||||
|
|
@ -222,7 +230,7 @@ void LLPluginProcessParent::idle(void)
|
|||
LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
|
||||
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -234,7 +242,7 @@ void LLPluginProcessParent::idle(void)
|
|||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +250,7 @@ void LLPluginProcessParent::idle(void)
|
|||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -255,7 +263,7 @@ void LLPluginProcessParent::idle(void)
|
|||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
killSockets();
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +282,7 @@ void LLPluginProcessParent::idle(void)
|
|||
mProcess.addArgument(stream.str());
|
||||
if(mProcess.launch() != 0)
|
||||
{
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -290,7 +298,7 @@ void LLPluginProcessParent::idle(void)
|
|||
// waiting for the plugin to connect
|
||||
if(pluginLockedUpOrQuit())
|
||||
{
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -309,7 +317,7 @@ void LLPluginProcessParent::idle(void)
|
|||
|
||||
if(pluginLockedUpOrQuit())
|
||||
{
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -330,14 +338,14 @@ void LLPluginProcessParent::idle(void)
|
|||
// The load_plugin_response message will kick us from here into STATE_RUNNING
|
||||
if(pluginLockedUpOrQuit())
|
||||
{
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_RUNNING:
|
||||
if(pluginLockedUpOrQuit())
|
||||
{
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -349,10 +357,18 @@ void LLPluginProcessParent::idle(void)
|
|||
else if(pluginLockedUp())
|
||||
{
|
||||
LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl;
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_LAUNCH_FAILURE:
|
||||
if(mOwner != NULL)
|
||||
{
|
||||
mOwner->pluginLaunchFailed();
|
||||
}
|
||||
setState(STATE_CLEANUP);
|
||||
break;
|
||||
|
||||
case STATE_ERROR:
|
||||
if(mOwner != NULL)
|
||||
{
|
||||
|
|
@ -467,7 +483,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
|
|||
else
|
||||
{
|
||||
LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -497,7 +513,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
|
|||
else
|
||||
{
|
||||
LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
|
||||
setState(STATE_ERROR);
|
||||
errorState();
|
||||
}
|
||||
}
|
||||
else if(message_name == "heartbeat")
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
virtual ~LLPluginProcessParentOwner();
|
||||
virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
|
||||
// This will only be called when the plugin has died unexpectedly
|
||||
virtual void pluginLaunchFailed() {};
|
||||
virtual void pluginDied() {};
|
||||
};
|
||||
|
||||
|
|
@ -68,6 +69,9 @@ public:
|
|||
bool isDone(void);
|
||||
|
||||
void killSockets(void);
|
||||
|
||||
// Go to the proper error state
|
||||
void errorState(void);
|
||||
|
||||
void setSleepTime(F64 sleep_time, bool force_send = false);
|
||||
F64 getSleepTime(void) const { return mSleepTime; };
|
||||
|
|
@ -110,6 +114,7 @@ private:
|
|||
STATE_HELLO, // first message from the plugin process has been received
|
||||
STATE_LOADING, // process has been asked to load the plugin
|
||||
STATE_RUNNING, //
|
||||
STATE_LAUNCH_FAILURE, // Failure before plugin loaded
|
||||
STATE_ERROR, // generic bailout state
|
||||
STATE_CLEANUP, // clean everything up
|
||||
STATE_EXITING, // Tried to kill process, waiting for it to exit
|
||||
|
|
|
|||
|
|
@ -903,6 +903,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
|
|||
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
|
||||
};
|
||||
break;
|
||||
|
||||
case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
|
||||
{
|
||||
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
|
||||
};
|
||||
break;
|
||||
};
|
||||
|
||||
// chain all events to any potential observers of this object.
|
||||
|
|
|
|||
|
|
@ -1381,6 +1381,18 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
|
|||
{
|
||||
switch(event)
|
||||
{
|
||||
case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
|
||||
{
|
||||
// The plugin failed to load properly. Make sure the timer doesn't retry.
|
||||
mMediaSourceFailedInit = true;
|
||||
|
||||
// TODO: may want a different message for this case?
|
||||
LLSD args;
|
||||
args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
|
||||
LLNotifications::instance().add("MediaPluginFailed", args);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_EVENT_PLUGIN_FAILED:
|
||||
{
|
||||
LLSD args;
|
||||
|
|
|
|||
|
|
@ -544,6 +544,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
|
|||
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
|
||||
};
|
||||
break;
|
||||
|
||||
case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
|
||||
{
|
||||
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
|
||||
};
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2033,6 +2033,10 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
|
|||
case MEDIA_EVENT_PLUGIN_FAILED:
|
||||
std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
|
||||
break;
|
||||
|
||||
case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
|
||||
std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue