Files
SingularityViewer/indra/llplugin/llpluginprocessparent.h
2010-04-02 02:48:44 -03:00

170 lines
5.7 KiB
C++

/**
* @file llpluginprocessparent.h
* @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008-2009, 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
* ("GPL"), unless you have obtained a separate licensing agreement
* ("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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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$
*/
#ifndef LL_LLPLUGINPROCESSPARENT_H
#define LL_LLPLUGINPROCESSPARENT_H
#include "llapr.h"
#include "llprocesslauncher.h"
#include "llpluginmessage.h"
#include "llpluginmessagepipe.h"
#include "llpluginsharedmemory.h"
#include "lliosocket.h"
class LLPluginProcessParentOwner
{
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() {};
};
class LLPluginProcessParent : public LLPluginMessagePipeOwner
{
LOG_CLASS(LLPluginProcessParent);
public:
LLPluginProcessParent(LLPluginProcessParentOwner *owner);
~LLPluginProcessParent();
void init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path);
void idle(void);
// returns true if the plugin is on its way to steady state
bool isLoading(void);
// returns true if the plugin is in the steady state (processing messages)
bool isRunning(void);
// returns true if the process has exited or we've had a fatal error
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; };
void sendMessage(const LLPluginMessage &message);
void receiveMessage(const LLPluginMessage &message);
// Inherited from LLPluginMessagePipeOwner
void receiveMessageRaw(const std::string &message);
// This adds a memory segment shared with the client, generating a name for the segment. The name generated is guaranteed to be unique on the host.
// The caller must call removeSharedMemory first (and wait until getSharedMemorySize returns 0 for the indicated name) before re-adding a segment with the same name.
std::string addSharedMemory(size_t size);
// Negotiates for the removal of a shared memory segment. It is the caller's responsibility to ensure that nothing touches the memory
// after this has been called, since the segment will be unmapped shortly thereafter.
void removeSharedMemory(const std::string &name);
size_t getSharedMemorySize(const std::string &name);
void *getSharedMemoryAddress(const std::string &name);
// Returns the version string the plugin indicated for the message class, or an empty string if that class wasn't in the list.
std::string getMessageClassVersion(const std::string &message_class);
std::string getPluginVersion(void);
bool getDisableTimeout() { return mDisableTimeout; };
void setDisableTimeout(bool disable) { mDisableTimeout = disable; };
void setLaunchTimeout(F32 timeout) { mPluginLaunchTimeout = timeout; };
void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; };
F64 getCPUUsage() { return mCPUUsage; };
private:
enum EState
{
STATE_UNINITIALIZED,
STATE_INITIALIZED, // init() has been called
STATE_LISTENING, // listening for incoming connection
STATE_LAUNCHED, // process has been launched
STATE_CONNECTED, // process has connected
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
STATE_DONE //
};
EState mState;
void setState(EState state);
bool pluginLockedUp();
bool pluginLockedUpOrQuit();
bool accept();
LLSocket::ptr_t mListenSocket;
LLSocket::ptr_t mSocket;
U32 mBoundPort;
LLProcessLauncher mProcess;
std::string mPluginFile;
std::string mUserDataPath;
LLPluginProcessParentOwner *mOwner;
typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
sharedMemoryRegionsType mSharedMemoryRegions;
LLSD mMessageClassVersions;
std::string mPluginVersionString;
LLTimer mHeartbeat;
F64 mSleepTime;
F64 mCPUUsage;
bool mDisableTimeout;
bool mDebug;
LLProcessLauncher mDebugger;
F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch.
F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up.
};
#endif // LL_LLPLUGINPROCESSPARENT_H