phoenix-firestorm/indra/llcommon/llapp.h

324 lines
9.8 KiB
C++
Executable File

/**
* @file llapp.h
* @brief Declaration of the LLApp class.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLAPP_H
#define LL_LLAPP_H
#include <map>
#include "llrun.h"
#include "llsd.h"
// Forward declarations
template <typename Type> class LLAtomic32;
typedef LLAtomic32<U32> LLAtomicU32;
class LLErrorThread;
class LLLiveFile;
#if LL_LINUX
#include <signal.h>
#endif
typedef void (*LLAppErrorHandler)();
#if !LL_WINDOWS
extern S32 LL_SMACKDOWN_SIGNAL;
extern S32 LL_HEARTBEAT_SIGNAL;
// Clear all of the signal handlers (which we want to do for the child process when we fork
void clear_signals();
#endif
namespace google_breakpad {
class ExceptionHandler; // See exception_handler.h
}
class LL_COMMON_API LLApp
{
friend class LLErrorThread;
public:
typedef enum e_app_status
{
APP_STATUS_RUNNING, // The application is currently running - the default status
APP_STATUS_QUITTING, // The application is currently quitting - threads should listen for this and clean up
APP_STATUS_STOPPED, // The application is no longer running - tells the error thread it can exit
APP_STATUS_ERROR // The application had a fatal error occur - tells the error thread to run
} EAppStatus;
LLApp();
virtual ~LLApp();
protected:
LLApp(LLErrorThread* error_thread);
void commonCtor();
public:
/**
* @brief Return the static app instance if one was created.
*/
static LLApp* instance();
/** @name Runtime options */
//@{
/**
* @brief Enumeration to specify option priorities in highest to
* lowest order.
*/
enum OptionPriority
{
PRIORITY_RUNTIME_OVERRIDE,
PRIORITY_COMMAND_LINE,
PRIORITY_SPECIFIC_CONFIGURATION,
PRIORITY_GENERAL_CONFIGURATION,
PRIORITY_DEFAULT,
PRIORITY_COUNT
};
/**
* @brief Get the application option at the highest priority.
*
* If the return value is undefined, the option does not exist.
* @param name The name of the option.
* @return Returns the option data.
*/
LLSD getOption(const std::string& name) const;
/**
* @brief Parse command line options and insert them into
* application command line options.
*
* The name inserted into the option will have leading option
* identifiers (a minus or double minus) stripped. All options
* with values will be stored as a string, while all options
* without values will be stored as true.
* @param argc The argc passed into main().
* @param argv The argv passed into main().
* @return Returns true if the parse succeeded.
*/
bool parseCommandOptions(int argc, char** argv);
/**
* @brief Keep track of live files automatically.
*
* *TODO: it currently uses the <code>addToEventTimer()</code> API
* instead of the runner. I should probalby use the runner.
*
* *NOTE: DO NOT add the livefile instance to any kind of check loop.
*
* @param livefile A valid instance of an LLLiveFile. This LLApp
* instance will delete the livefile instance.
*/
void manageLiveFile(LLLiveFile* livefile);
/**
* @brief Set the options at the specified priority.
*
* This function completely replaces the options at the priority
* level with the data specified. This function will make sure
* level and data might be valid before doing the replace.
* @param level The priority level of the data.
* @param data The data to set.
* @return Returns true if the option was set.
*/
bool setOptionData(OptionPriority level, LLSD data);
/**
* @brief Get the option data at the specified priority.
*
* This method is probably not so useful except when merging
* information.
* @param level The priority level of the data.
* @return Returns The data (if any) at the level priority.
*/
LLSD getOptionData(OptionPriority level);
//@}
//
// Main application logic
//
virtual bool init() = 0; // Override to do application initialization
//
// cleanup()
//
// It's currently assumed that the cleanup() method will only get
// called from the main thread or the error handling thread, as it will
// likely do thread shutdown, among other things.
//
virtual bool cleanup() = 0; // Override to do application cleanup
//
// mainLoop()
//
// Runs the application main loop. It's assumed that when you exit
// this method, the application is in one of the cleanup states, either QUITTING or ERROR
//
virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
//
// Crash logging
//
void disableCrashlogger(); // Let the OS handle the crashes
static bool isCrashloggerDisabled(); // Get the here above set value
//
// Application status
//
static void setQuitting(); // Set status to QUITTING, the app is now shutting down
static void setStopped(); // Set status to STOPPED, the app is done running and should exit
static void setError(); // Set status to ERROR, the error handler should run
static bool isStopped();
static bool isRunning();
static bool isQuitting();
static bool isError();
static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
static int getPid();
/** @name Error handling methods */
//@{
/**
* @brief Do our generic platform-specific error-handling setup --
* signals on unix, structured exceptions on windows.
*
* DO call this method if your app will either spawn children or be
* spawned by a launcher.
* Call just after app object construction.
* (Otherwise your app will crash when getting signals,
* and will not core dump.)
*
* DO NOT call this method if your application has specialized
* error handling code.
*/
// void setupErrorHandling(bool mSecondInstance=false);
// [SL:KB] - Patch: Viewer-CrashReporting | Checked: 2010-11-12 (Catznip-2.6.0a) | Added: Catznip-2.4.0a
typedef enum minidump_type_t {
MINIDUMP_MINIMAL = 0,
MINIDUMP_NORMAL = 1,
MINIDUMP_EXTENDED = 2
} EMiniDumpType;
void setupErrorHandling(bool second_instance, EMiniDumpType minidump_type = MINIDUMP_NORMAL);
// [/SL:KB]
void setErrorHandler(LLAppErrorHandler handler);
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
//@}
// the maximum length of the minidump filename returned by getMiniDumpFilename()
static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
// change the directory where Breakpad minidump files are written to
void setMiniDumpDir(const std::string &path);
void setDebugFileNames(const std::string &path);
// Return the Google Breakpad minidump filename after a crash.
char *getMiniDumpFilename() { return mMinidumpPath; }
std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
// Write out a Google Breakpad minidump file.
void writeMiniDump();
/**
* @brief Get a reference to the application runner
*
* Please use the runner with caution. Since the Runner usage
* pattern is not yet clear, this method just gives access to it
* to add and remove runnables.
* @return Returns the application runner. Do not save the
* pointer past the caller's stack frame.
*/
LLRunner& getRunner() { return mRunner; }
public:
typedef std::map<std::string, std::string> string_map;
string_map mOptionMap; // Contains all command-line options and arguments in a map
protected:
static void setStatus(EAppStatus status); // Use this to change the application status.
static EAppStatus sStatus; // Reflects current application status
static BOOL sErrorThreadRunning; // Set while the error thread is running
static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.
std::string mDumpPath; //output path for google breakpad. Dependency workaround.
/**
* @brief This method is called once a frame to do once a frame tasks.
*/
void stepFrame();
private:
void startErrorThread();
// Contains the filename of the minidump file after a crash.
char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
std::string mStaticDebugFileName;
std::string mDynamicDebugFileName;
// *NOTE: On Windows, we need a routine to reset the structured
// exception handler when some evil driver has taken it over for
// their own purposes
typedef int(*signal_handler_func)(int signum);
static LLAppErrorHandler sErrorHandler;
// Default application threads
LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback
// This is the application level runnable scheduler.
LLRunner mRunner;
/** @name Runtime option implementation */
//@{
// The application options.
LLSD mOptions;
// The live files for this application
std::vector<LLLiveFile*> mLiveFiles;
//@}
private:
// the static application instance if it was created.
static LLApp* sApplication;
google_breakpad::ExceptionHandler * mExceptionHandler;
#if !LL_WINDOWS
friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
#endif
public:
static BOOL sLogInSignal;
};
#endif // LL_LLAPP_H