summaryrefslogtreecommitdiff
path: root/indra/llplugin
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llplugin')
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp2
-rw-r--r--indra/llplugin/llpluginclassmedia.h2
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h2
-rw-r--r--indra/llplugin/llplugininstance.cpp35
-rw-r--r--indra/llplugin/llplugininstance.h26
-rw-r--r--indra/llplugin/llpluginmessage.cpp168
-rw-r--r--indra/llplugin/llpluginmessage.h18
-rw-r--r--indra/llplugin/llpluginmessageclasses.h2
-rw-r--r--indra/llplugin/llpluginmessagepipe.cpp2
-rw-r--r--indra/llplugin/llpluginmessagepipe.h2
-rw-r--r--indra/llplugin/llpluginprocesschild.cpp2
-rw-r--r--indra/llplugin/llpluginprocesschild.h2
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp2
-rw-r--r--indra/llplugin/llpluginprocessparent.h2
-rw-r--r--indra/llplugin/llpluginsharedmemory.cpp2
-rw-r--r--indra/llplugin/llpluginsharedmemory.h2
-rw-r--r--indra/llplugin/slplugin/slplugin.cpp104
17 files changed, 338 insertions, 37 deletions
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index c3d8a5aa23..70d770ef7e 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -2,6 +2,7 @@
* @file llpluginclassmedia.cpp
* @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index dcc4a3bd6a..6b64688718 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -2,6 +2,7 @@
* @file llpluginclassmedia.h
* @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINCLASSMEDIA_H
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index c798af29ca..6d369cd51a 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -2,6 +2,7 @@
* @file llpluginclassmediaowner.h
* @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINCLASSMEDIAOWNER_H
diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp
index 58fb792d0d..44e3b4950f 100644
--- a/indra/llplugin/llplugininstance.cpp
+++ b/indra/llplugin/llplugininstance.cpp
@@ -2,6 +2,7 @@
* @file llplugininstance.cpp
* @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
@@ -35,13 +37,21 @@
#include "llapr.h"
-//virtual
+/** Virtual destructor. */
LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
{
}
+/**
+ * TODO:DOC describe how it's used
+ */
const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoint";
+/**
+ * Constructor.
+ *
+ * @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is?
+ */
LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) :
mDSOHandle(NULL),
mPluginUserData(NULL),
@@ -50,6 +60,9 @@ LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) :
mOwner = owner;
}
+/**
+ * Destructor.
+ */
LLPluginInstance::~LLPluginInstance()
{
if(mDSOHandle != NULL)
@@ -59,6 +72,12 @@ LLPluginInstance::~LLPluginInstance()
}
}
+/**
+ * Dynamically loads the plugin and runs the plugin's init function.
+ *
+ * @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h
+ * @return 0 if successful, APR error code or error code from the plugin's init function on failure.
+ */
int LLPluginInstance::load(std::string &plugin_file)
{
pluginInitFunction init_function = NULL;
@@ -100,6 +119,11 @@ int LLPluginInstance::load(std::string &plugin_file)
return (int)result;
}
+/**
+ * Sends a message to the plugin.
+ *
+ * @param[in] message Message
+ */
void LLPluginInstance::sendMessage(const std::string &message)
{
if(mPluginSendMessageFunction)
@@ -113,6 +137,10 @@ void LLPluginInstance::sendMessage(const std::string &message)
}
}
+/**
+ * Idle. TODO:DOC what's the purpose of this?
+ *
+ */
void LLPluginInstance::idle(void)
{
}
@@ -126,6 +154,11 @@ void LLPluginInstance::staticReceiveMessage(const char *message_string, void **u
self->receiveMessage(message_string);
}
+/**
+ * Plugin receives message from plugin loader shell.
+ *
+ * @param[in] message_string Message
+ */
void LLPluginInstance::receiveMessage(const char *message_string)
{
if(mOwner)
diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h
index ba569df10c..c11d5ab5d4 100644
--- a/indra/llplugin/llplugininstance.h
+++ b/indra/llplugin/llplugininstance.h
@@ -1,7 +1,7 @@
/**
* @file llplugininstance.h
- * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +27,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGININSTANCE_H
@@ -37,13 +38,20 @@
#include "apr_dso.h"
+/**
+ * @brief LLPluginInstanceMessageListener receives messages sent from the plugin loader shell to the plugin.
+ */
class LLPluginInstanceMessageListener
{
public:
virtual ~LLPluginInstanceMessageListener();
+ /** Plugin receives message from plugin loader shell. */
virtual void receivePluginMessage(const std::string &message) = 0;
};
+/**
+ * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
+ */
class LLPluginInstance
{
LOG_CLASS(LLPluginInstance);
@@ -58,19 +66,27 @@ public:
// Sends a message to the plugin.
void sendMessage(const std::string &message);
+ // TODO:DOC is this comment obsolete? can't find "send_count" anywhere in indra tree.
// send_count is the maximum number of message to process from the send queue. If negative, it will drain the queue completely.
// The receive queue is always drained completely.
// Returns the total number of messages processed from both queues.
void idle(void);
- // this is the signature of the "send a message" function.
- // message_string is a null-terminated C string
- // user_data is the opaque reference that the callee supplied during setup.
+ /** The signature of the function for sending a message from plugin to plugin loader shell.
+ *
+ * @param[in] message_string Null-terminated C string
+ * @param[in] user_data The opaque reference that the callee supplied during setup.
+ */
typedef void (*sendMessageFunction) (const char *message_string, void **user_data);
- // signature of the plugin init function
+ /** The signature of the plugin init function. TODO:DOC check direction (pluging loader shell to plugin?)
+ *
+ * @param[in] host_user_data Data from plugin loader shell.
+ * @param[in] plugin_send_function Function for sending from the plugin loader shell to plugin.
+ */
typedef int (*pluginInitFunction) (sendMessageFunction host_send_func, void *host_user_data, sendMessageFunction *plugin_send_func, void **plugin_user_data);
+ /** Name of plugin init function */
static const char *PLUGIN_INIT_FUNCTION_NAME;
private:
diff --git a/indra/llplugin/llpluginmessage.cpp b/indra/llplugin/llpluginmessage.cpp
index 32601b47db..f76d848a70 100644
--- a/indra/llplugin/llpluginmessage.cpp
+++ b/indra/llplugin/llpluginmessage.cpp
@@ -2,6 +2,7 @@
* @file llpluginmessage.cpp
* @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
@@ -35,31 +37,57 @@
#include "llsdserialize.h"
#include "u64.h"
+/**
+ * Constructor.
+ */
LLPluginMessage::LLPluginMessage()
{
}
+/**
+ * Constructor.
+ *
+ * @param[in] p Existing message
+ */
LLPluginMessage::LLPluginMessage(const LLPluginMessage &p)
{
mMessage = p.mMessage;
}
+/**
+ * Constructor.
+ *
+ * @param[in] message_class Message class
+ * @param[in] message_name Message name
+ */
LLPluginMessage::LLPluginMessage(const std::string &message_class, const std::string &message_name)
{
setMessage(message_class, message_name);
}
+/**
+ * Destructor.
+ */
LLPluginMessage::~LLPluginMessage()
{
}
+/**
+ * Reset all internal state.
+ */
void LLPluginMessage::clear()
{
mMessage = LLSD::emptyMap();
mMessage["params"] = LLSD::emptyMap();
}
+/**
+ * Sets the message class and name. Also has the side-effect of clearing any key-value pairs in the message.
+ *
+ * @param[in] message_class Message class
+ * @param[in] message_name Message name
+ */
void LLPluginMessage::setMessage(const std::string &message_class, const std::string &message_name)
{
clear();
@@ -67,21 +95,45 @@ void LLPluginMessage::setMessage(const std::string &message_class, const std::st
mMessage["name"] = message_name;
}
+/**
+ * Sets a key/value pair in the message, where the value is a string.
+ *
+ * @param[in] key Key
+ * @param[in] value String value
+ */
void LLPluginMessage::setValue(const std::string &key, const std::string &value)
{
mMessage["params"][key] = value;
}
+/**
+ * Sets a key/value pair in the message, where the value is LLSD.
+ *
+ * @param[in] key Key
+ * @param[in] value LLSD value
+ */
void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value)
{
mMessage["params"][key] = value;
}
+/**
+ * Sets a key/value pair in the message, where the value is signed 32-bit.
+ *
+ * @param[in] key Key
+ * @param[in] value 32-bit signed value
+ */
void LLPluginMessage::setValueS32(const std::string &key, S32 value)
{
mMessage["params"][key] = value;
}
+/**
+ * Sets a key/value pair in the message, where the value is unsigned 32-bit. The value is stored as a string beginning with "0x".
+ *
+ * @param[in] key Key
+ * @param[in] value 32-bit unsigned value
+ */
void LLPluginMessage::setValueU32(const std::string &key, U32 value)
{
std::stringstream temp;
@@ -89,16 +141,34 @@ void LLPluginMessage::setValueU32(const std::string &key, U32 value)
setValue(key, temp.str());
}
+/**
+ * Sets a key/value pair in the message, where the value is a bool.
+ *
+ * @param[in] key Key
+ * @param[in] value Boolean value
+ */
void LLPluginMessage::setValueBoolean(const std::string &key, bool value)
{
mMessage["params"][key] = value;
}
+/**
+ * Sets a key/value pair in the message, where the value is a double.
+ *
+ * @param[in] key Key
+ * @param[in] value Boolean value
+ */
void LLPluginMessage::setValueReal(const std::string &key, F64 value)
{
mMessage["params"][key] = value;
}
+/**
+ * Sets a key/value pair in the message, where the value is a pointer. The pointer is stored as a string.
+ *
+ * @param[in] key Key
+ * @param[in] value Pointer value
+ */
void LLPluginMessage::setValuePointer(const std::string &key, void* value)
{
std::stringstream temp;
@@ -107,16 +177,33 @@ void LLPluginMessage::setValuePointer(const std::string &key, void* value)
setValue(key, temp.str());
}
+/**
+ * Gets the message class.
+ *
+ * @return Message class
+ */
std::string LLPluginMessage::getClass(void) const
{
return mMessage["class"];
}
+/**
+ * Gets the message name.
+ *
+ * @return Message name
+ */
std::string LLPluginMessage::getName(void) const
{
return mMessage["name"];
}
+/**
+ * Returns true if the specified key exists in this message (useful for optional parameters).
+ *
+ * @param[in] key Key
+ *
+ * @return True if key exists, false otherwise.
+ */
bool LLPluginMessage::hasValue(const std::string &key) const
{
bool result = false;
@@ -129,6 +216,13 @@ bool LLPluginMessage::hasValue(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as a string. If the key does not exist, an empty string will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return String value of key if key exists, empty string if key does not exist.
+ */
std::string LLPluginMessage::getValue(const std::string &key) const
{
std::string result;
@@ -141,6 +235,13 @@ std::string LLPluginMessage::getValue(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return LLSD value of key if key exists, null LLSD if key does not exist.
+ */
LLSD LLPluginMessage::getValueLLSD(const std::string &key) const
{
LLSD result;
@@ -153,6 +254,13 @@ LLSD LLPluginMessage::getValueLLSD(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Signed 32-bit int value of key if key exists, 0 if key does not exist.
+ */
S32 LLPluginMessage::getValueS32(const std::string &key) const
{
S32 result = 0;
@@ -165,6 +273,13 @@ S32 LLPluginMessage::getValueS32(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Unsigned 32-bit int value of key if key exists, 0 if key does not exist.
+ */
U32 LLPluginMessage::getValueU32(const std::string &key) const
{
U32 result = 0;
@@ -179,6 +294,13 @@ U32 LLPluginMessage::getValueU32(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as a bool. If the key does not exist, false will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Boolean value of key if it exists, false otherwise.
+ */
bool LLPluginMessage::getValueBoolean(const std::string &key) const
{
bool result = false;
@@ -191,6 +313,13 @@ bool LLPluginMessage::getValueBoolean(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as a double. If the key does not exist, 0 will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Value as a double if key exists, 0 otherwise.
+ */
F64 LLPluginMessage::getValueReal(const std::string &key) const
{
F64 result = 0.0f;
@@ -203,6 +332,13 @@ F64 LLPluginMessage::getValueReal(const std::string &key) const
return result;
}
+/**
+ * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Pointer value if key exists, NULL otherwise.
+ */
void* LLPluginMessage::getValuePointer(const std::string &key) const
{
void* result = NULL;
@@ -217,6 +353,11 @@ void* LLPluginMessage::getValuePointer(const std::string &key) const
return result;
}
+/**
+ * Flatten the message into a string.
+ *
+ * @return Message as a string.
+ */
std::string LLPluginMessage::generate(void) const
{
std::ostringstream result;
@@ -228,7 +369,11 @@ std::string LLPluginMessage::generate(void) const
return result.str();
}
-
+/**
+ * Parse an incoming message into component parts. Clears all existing state before starting the parse.
+ *
+ * @return Returns -1 on failure, otherwise returns the number of key/value pairs in the incoming message.
+ */
int LLPluginMessage::parse(const std::string &message)
{
// clear any previous state
@@ -242,27 +387,48 @@ int LLPluginMessage::parse(const std::string &message)
}
+/**
+ * Destructor
+ */
LLPluginMessageListener::~LLPluginMessageListener()
{
// TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted?
}
+/**
+ * Destructor
+ */
LLPluginMessageDispatcher::~LLPluginMessageDispatcher()
{
}
+/**
+ * Add a message listener. TODO:DOC need more info on what uses this. when are multiple listeners needed?
+ *
+ * @param[in] listener Message listener
+ */
void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener *listener)
{
mListeners.insert(listener);
}
+/**
+ * Remove a message listener.
+ *
+ * @param[in] listener Message listener
+ */
void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListener *listener)
{
mListeners.erase(listener);
}
+/**
+ * Distribute a message to all message listeners.
+ *
+ * @param[in] message Message
+ */
void LLPluginMessageDispatcher::dispatchPluginMessage(const LLPluginMessage &message)
{
for (listener_set_t::iterator it = mListeners.begin();
diff --git a/indra/llplugin/llpluginmessage.h b/indra/llplugin/llpluginmessage.h
index 5e93d8b7a1..cbd31e0964 100644
--- a/indra/llplugin/llpluginmessage.h
+++ b/indra/llplugin/llpluginmessage.h
@@ -1,7 +1,7 @@
/**
* @file llpluginmessage.h
- * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +27,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINMESSAGE_H
@@ -34,7 +35,9 @@
#include "llsd.h"
-
+/**
+ * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
+ */
class LLPluginMessage
{
LOG_CLASS(LLPluginMessage);
@@ -102,14 +105,23 @@ private:
};
+/**
+ * @brief Listener for plugin messages.
+ */
class LLPluginMessageListener
{
public:
virtual ~LLPluginMessageListener();
+ /** Plugin receives message from plugin loader shell. */
virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
};
+/**
+ * @brief Dispatcher for plugin messages.
+ *
+ * Manages the set of plugin message listeners and distributes messages to plugin message listeners.
+ */
class LLPluginMessageDispatcher
{
public:
@@ -120,7 +132,9 @@ public:
protected:
void dispatchPluginMessage(const LLPluginMessage &message);
+ /** A set of message listeners. */
typedef std::set<LLPluginMessageListener*> listener_set_t;
+ /** The set of message listeners. */
listener_set_t mListeners;
};
diff --git a/indra/llplugin/llpluginmessageclasses.h b/indra/llplugin/llpluginmessageclasses.h
index 927fcf2eb2..01fddb92c5 100644
--- a/indra/llplugin/llpluginmessageclasses.h
+++ b/indra/llplugin/llpluginmessageclasses.h
@@ -2,6 +2,7 @@
* @file llpluginmessageclasses.h
* @brief This file defines the versions of existing message classes for LLPluginMessage.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINMESSAGECLASSES_H
diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp
index 31ea138912..cc193fca42 100644
--- a/indra/llplugin/llpluginmessagepipe.cpp
+++ b/indra/llplugin/llpluginmessagepipe.cpp
@@ -2,6 +2,7 @@
* @file llpluginmessagepipe.cpp
* @brief Classes that implement connections from the plugin system to pipes/pumps.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h
index 4eb6575bd4..1ddb38de68 100644
--- a/indra/llplugin/llpluginmessagepipe.h
+++ b/indra/llplugin/llpluginmessagepipe.h
@@ -2,6 +2,7 @@
* @file llpluginmessagepipe.h
* @brief Classes that implement connections from the plugin system to pipes/pumps.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINMESSAGEPIPE_H
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index fc95136d9e..55cf11c620 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -2,6 +2,7 @@
* @file llpluginprocesschild.cpp
* @brief LLPluginProcessChild handles the child side of the external-process plugin API.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h
index 75860bdf0a..f5c57c3d49 100644
--- a/indra/llplugin/llpluginprocesschild.h
+++ b/indra/llplugin/llpluginprocesschild.h
@@ -2,6 +2,7 @@
* @file llpluginprocesschild.h
* @brief LLPluginProcessChild handles the child side of the external-process plugin API.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINPROCESSCHILD_H
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index b7ce800c3a..332ce288d7 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -2,6 +2,7 @@
* @file llpluginprocessparent.cpp
* @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 1289e86c13..25669f5d78 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -2,6 +2,7 @@
* @file llpluginprocessparent.h
* @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINPROCESSPARENT_H
diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp
index ce8b8e3e09..3c69a69d28 100644
--- a/indra/llplugin/llpluginsharedmemory.cpp
+++ b/indra/llplugin/llpluginsharedmemory.cpp
@@ -2,6 +2,7 @@
* @file llpluginsharedmemory.cpp
* @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#include "linden_common.h"
diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h
index a4613b9a54..4014620c52 100644
--- a/indra/llplugin/llpluginsharedmemory.h
+++ b/indra/llplugin/llpluginsharedmemory.h
@@ -2,6 +2,7 @@
* @file llpluginsharedmemory.h
* @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
*
+ * @cond
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
@@ -27,6 +28,7 @@
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ * @endcond
*/
#ifndef LL_LLPLUGINSHAREDMEMORY_H
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
index 005e427572..23dc532ba5 100644
--- a/indra/llplugin/slplugin/slplugin.cpp
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -1,11 +1,13 @@
-/**
+/**
* @file slplugin.cpp
* @brief Loader shell for plugins, intended to be launched by the plugin host application, which directly loads a plugin dynamic library.
*
+ * @cond
+ *
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008, Linden Research, Inc.
- *
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
@@ -13,20 +15,22 @@
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
- *
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
- *
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
+ *
+ * @endcond
*/
@@ -48,15 +52,15 @@
/*
On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist.
-
+
Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags:
-
+
-sectcreate __TEXT __info_plist /path/to/slplugin_info.plist
-
+
which means adding this to the gcc flags:
-
+
-Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist
-
+
*/
#if LL_DARWIN || LL_LINUX
@@ -67,7 +71,7 @@ static void crash_handler(int sig)
// TODO: add our own crash reporting
_exit(1);
}
-#endif
+#endif
#if LL_WINDOWS
#include <windows.h>
@@ -80,7 +84,48 @@ LONG WINAPI myWin32ExceptionHandler( struct _EXCEPTION_POINTERS* exception_infop
//std::cerr << "intercepted an unhandled exception and will exit immediately." << std::endl;
// TODO: replace exception handler before we exit?
- return EXCEPTION_EXECUTE_HANDLER;
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+// Taken from : http://blog.kalmbachnet.de/?postid=75
+// The MSVC 2005 CRT forces the call of the default-debugger (normally Dr.Watson)
+// even with the other exception handling code. This (terrifying) piece of code
+// patches things so that doesn't happen.
+LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(
+ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter )
+{
+ return NULL;
+}
+
+BOOL PreventSetUnhandledExceptionFilter()
+{
+// WARNING: This won't work on 64-bit Windows systems so we turn it off it.
+// It should work for any flavor of 32-bit Windows we care about.
+// If it's off, sometimes you will see an OS message when a plugin crashes
+#ifndef _WIN64
+ HMODULE hKernel32 = LoadLibraryA( "kernel32.dll" );
+ if ( NULL == hKernel32 )
+ return FALSE;
+
+ void *pOrgEntry = GetProcAddress( hKernel32, "SetUnhandledExceptionFilter" );
+ if( NULL == pOrgEntry )
+ return FALSE;
+
+ unsigned char newJump[ 100 ];
+ DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
+ dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
+ void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
+ DWORD dwNewEntryAddr = (DWORD) pNewFunc;
+ DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
+
+ newJump[ 0 ] = 0xE9; // JMP absolute
+ memcpy( &newJump[ 1 ], &dwRelativeAddr, sizeof( pNewFunc ) );
+ SIZE_T bytesWritten;
+ BOOL bRet = WriteProcessMemory( GetCurrentProcess(), pOrgEntry, newJump, sizeof( pNewFunc ) + 1, &bytesWritten );
+ return bRet;
+#else
+ return FALSE;
+#endif
}
////////////////////////////////////////////////////////////////////////////////
@@ -91,6 +136,7 @@ void initExceptionHandler()
// save old exception handler in case we need to restore it at the end
prev_filter = SetUnhandledExceptionFilter( myWin32ExceptionHandler );
+ PreventSetUnhandledExceptionFilter();
}
bool checkExceptionHandler()
@@ -99,6 +145,8 @@ bool checkExceptionHandler()
LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
prev_filter = SetUnhandledExceptionFilter(myWin32ExceptionHandler);
+ PreventSetUnhandledExceptionFilter();
+
if (prev_filter != myWin32ExceptionHandler)
{
LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with " << prev_filter << "!" << LL_ENDL;
@@ -122,7 +170,7 @@ bool checkExceptionHandler()
}
#endif
-// If this application on Windows platform is a console application, a console is always
+// If this application on Windows platform is a console application, a console is always
// created which is bad. Making it a Windows "application" via CMake settings but not
// adding any code to explicitly create windows does the right thing.
#if LL_WINDOWS
@@ -133,7 +181,7 @@ int main(int argc, char **argv)
{
ll_init_apr();
- // Set up llerror logging
+ // Set up llerror logging
{
LLError::initForApplication(".");
LLError::setDefaultLevel(LLError::LEVEL_INFO);
@@ -146,14 +194,14 @@ int main(int argc, char **argv)
{
LL_ERRS("slplugin") << "usage: " << "SLPlugin" << " launcher_port" << LL_ENDL;
};
-
+
U32 port = 0;
if(!LLStringUtil::convertToU32(lpCmdLine, port))
{
LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
};
- // Insert our exception handler into the system so this plugin doesn't
+ // Insert our exception handler into the system so this plugin doesn't
// display a crash message if something bad happens. The host app will
// see the missing heartbeat and log appropriately.
initExceptionHandler();
@@ -162,7 +210,7 @@ int main(int argc, char **argv)
{
LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL;
}
-
+
U32 port = 0;
if(!LLStringUtil::convertToU32(argv[1], port))
{
@@ -183,17 +231,17 @@ int main(int argc, char **argv)
LLPluginProcessChild *plugin = new LLPluginProcessChild();
plugin->init(port);
-
+
LLTimer timer;
timer.start();
#if LL_WINDOWS
checkExceptionHandler();
#endif
-
+
while(!plugin->isDone())
{
- timer.reset();
+ timer.reset();
plugin->idle();
#if LL_DARWIN
{
@@ -204,7 +252,7 @@ int main(int argc, char **argv)
#endif
F64 elapsed = timer.getElapsedTimeF64();
F64 remaining = plugin->getSleepTime() - elapsed;
-
+
if(remaining <= 0.0f)
{
// We've already used our full allotment.
@@ -217,26 +265,26 @@ int main(int argc, char **argv)
{
// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, sleeping for " << remaining * 1000.0f << " ms" << LL_ENDL;
-// timer.reset();
-
+// timer.reset();
+
// This also services the network as needed.
plugin->sleep(remaining);
-
+
// LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL;
}
#if LL_WINDOWS
// More agressive checking of interfering exception handlers.
- // Doesn't appear to be required so far - even for plugins
- // that do crash with a single call to the intercept
+ // Doesn't appear to be required so far - even for plugins
+ // that do crash with a single call to the intercept
// exception handler such as QuickTime.
//checkExceptionHandler();
#endif
}
delete plugin;
-
- ll_cleanup_apr();
+
+ ll_cleanup_apr();
return 0;
}