PageRenderTime 25ms CodeModel.GetById 13ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llapp.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 345 lines | 127 code | 55 blank | 163 comment | 0 complexity | ec71e507be7188c3b3bc62e938a56a54 MD5 | raw file
  1/** 
  2 * @file llapp.h
  3 * @brief Declaration of the LLApp class.
  4 *
  5 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLAPP_H
 28#define LL_LLAPP_H
 29
 30#include <map>
 31#include "llrun.h"
 32#include "llsd.h"
 33#include "lloptioninterface.h"
 34
 35// Forward declarations
 36template <typename Type> class LLAtomic32;
 37typedef LLAtomic32<U32> LLAtomicU32;
 38class LLErrorThread;
 39class LLLiveFile;
 40#if LL_LINUX
 41typedef struct siginfo siginfo_t;
 42#endif
 43
 44typedef void (*LLAppErrorHandler)();
 45typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
 46
 47#if !LL_WINDOWS
 48extern S32 LL_SMACKDOWN_SIGNAL;
 49extern S32 LL_HEARTBEAT_SIGNAL;
 50
 51// Clear all of the signal handlers (which we want to do for the child process when we fork
 52void clear_signals();
 53
 54class LLChildInfo
 55{
 56public:
 57	LLChildInfo() : mGotSigChild(FALSE), mCallback(NULL) {}
 58	BOOL mGotSigChild;
 59	LLAppChildCallback mCallback;
 60};
 61#endif
 62
 63namespace google_breakpad {
 64	class ExceptionHandler; // See exception_handler.h
 65}
 66
 67class LL_COMMON_API LLApp : public LLOptionInterface
 68{
 69	friend class LLErrorThread;
 70public:
 71	typedef enum e_app_status
 72	{
 73		APP_STATUS_RUNNING,		// The application is currently running - the default status
 74		APP_STATUS_QUITTING,	// The application is currently quitting - threads should listen for this and clean up
 75		APP_STATUS_STOPPED,		// The application is no longer running - tells the error thread it can exit
 76		APP_STATUS_ERROR		// The application had a fatal error occur - tells the error thread to run
 77	} EAppStatus;
 78
 79
 80	LLApp();
 81	virtual ~LLApp();
 82
 83protected:
 84	LLApp(LLErrorThread* error_thread);
 85	void commonCtor();
 86public:
 87	
 88	/** 
 89	 * @brief Return the static app instance if one was created.
 90	 */
 91	static LLApp* instance();
 92
 93	/** @name Runtime options */
 94	//@{
 95	/** 
 96	 * @brief Enumeration to specify option priorities in highest to
 97	 * lowest order.
 98	 */
 99	enum OptionPriority
100	{
101		PRIORITY_RUNTIME_OVERRIDE,
102		PRIORITY_COMMAND_LINE,
103		PRIORITY_SPECIFIC_CONFIGURATION,
104		PRIORITY_GENERAL_CONFIGURATION,
105		PRIORITY_DEFAULT,
106		PRIORITY_COUNT
107	};
108
109	/**
110	 * @brief Get the application option at the highest priority.
111	 *
112	 * If the return value is undefined, the option does not exist.
113	 * @param name The name of the option.
114	 * @return Returns the option data.
115	 */
116	virtual LLSD getOption(const std::string& name) const;
117
118	/** 
119	 * @brief Parse command line options and insert them into
120	 * application command line options.
121	 *
122	 * The name inserted into the option will have leading option
123	 * identifiers (a minus or double minus) stripped. All options
124	 * with values will be stored as a string, while all options
125	 * without values will be stored as true.
126	 * @param argc The argc passed into main().
127	 * @param argv The argv passed into main().
128	 * @return Returns true if the parse succeeded.
129	 */
130	bool parseCommandOptions(int argc, char** argv);
131
132	/**
133	 * @brief Keep track of live files automatically.
134	 *
135	 * *TODO: it currently uses the <code>addToEventTimer()</code> API
136	 * instead of the runner. I should probalby use the runner.
137	 *
138	 * *NOTE: DO NOT add the livefile instance to any kind of check loop.
139	 *
140	 * @param livefile A valid instance of an LLLiveFile. This LLApp
141	 * instance will delete the livefile instance.
142	 */
143	void manageLiveFile(LLLiveFile* livefile);
144
145	/**
146	 * @brief Set the options at the specified priority.
147	 *
148	 * This function completely replaces the options at the priority
149	 * level with the data specified. This function will make sure
150	 * level and data might be valid before doing the replace.
151	 * @param level The priority level of the data.
152	 * @param data The data to set.
153	 * @return Returns true if the option was set.
154	 */
155	bool setOptionData(OptionPriority level, LLSD data);
156
157	/**
158	 * @brief Get the option data at the specified priority.
159	 *
160	 * This method is probably not so useful except when merging
161	 * information.
162	 * @param level The priority level of the data.
163	 * @return Returns The data (if any) at the level priority.
164	 */
165	LLSD getOptionData(OptionPriority level);
166	//@}
167
168
169
170	//
171	// Main application logic
172	//
173	virtual bool init() = 0;			// Override to do application initialization
174
175	//
176	// cleanup()
177	//
178	// It's currently assumed that the cleanup() method will only get
179	// called from the main thread or the error handling thread, as it will
180	// likely do thread shutdown, among other things.
181	//
182	virtual bool cleanup() = 0;			// Override to do application cleanup
183
184	//
185	// mainLoop()
186	//
187	// Runs the application main loop.  It's assumed that when you exit
188	// this method, the application is in one of the cleanup states, either QUITTING or ERROR
189	//
190	virtual bool mainLoop() = 0; // Override for the application main loop.  Needs to at least gracefully notice the QUITTING state and exit.
191
192	//
193	// Crash logging
194	//
195	void disableCrashlogger();				// Let the OS handle the crashes
196	static bool isCrashloggerDisabled();	// Get the here above set value
197
198	//
199	// Application status
200	//
201	static void setQuitting();	// Set status to QUITTING, the app is now shutting down
202	static void setStopped();	// Set status to STOPPED, the app is done running and should exit
203	static void setError();		// Set status to ERROR, the error handler should run
204	static bool isStopped();
205	static bool isRunning();
206	static bool isQuitting();
207	static bool isError();
208	static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
209#if !LL_WINDOWS
210	static U32  getSigChildCount();
211	static void incSigChildCount();
212#endif
213	static int getPid();
214
215	/** @name Error handling methods */
216	//@{
217	/**
218	 * @brief Do our generic platform-specific error-handling setup --
219	 * signals on unix, structured exceptions on windows.
220	 * 
221	 * DO call this method if your app will either spawn children or be
222	 * spawned by a launcher.
223	 * Call just after app object construction.
224	 * (Otherwise your app will crash when getting signals,
225	 * and will not core dump.)
226	 *
227	 * DO NOT call this method if your application has specialized
228	 * error handling code.
229	 */
230	void setupErrorHandling();
231
232	void setErrorHandler(LLAppErrorHandler handler);
233	static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
234	//@}
235	
236	// the maximum length of the minidump filename returned by getMiniDumpFilename()
237	static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
238
239	// change the directory where Breakpad minidump files are written to
240	void setMiniDumpDir(const std::string &path);
241
242	// Return the Google Breakpad minidump filename after a crash.
243	char *getMiniDumpFilename() { return minidump_path; }
244
245	// Write out a Google Breakpad minidump file.
246	void writeMiniDump();
247
248#if !LL_WINDOWS
249	//
250	// Child process handling (Unix only for now)
251	//
252	// Set a callback to be run on exit of a child process
253	// WARNING!  This callback is run from the signal handler due to
254	// Linux threading requiring waitpid() to be called from the thread that spawned the process.
255	// At some point I will make this more behaved, but I'm not going to fix this right now - djs
256	void setChildCallback(pid_t pid, LLAppChildCallback callback);
257
258    // The child callback to run if no specific handler is set
259	void setDefaultChildCallback(LLAppChildCallback callback); 
260	
261    // Fork and do the proper signal handling/error handling mojo
262	// *NOTE: You need to make sure your signal handling callback is
263	// correct after you fork, because not all threads are duplicated
264	// when you fork!
265	pid_t fork(); 
266#endif
267
268	/**
269	  * @brief Get a reference to the application runner
270	  *
271	  * Please use the runner with caution. Since the Runner usage
272	  * pattern is not yet clear, this method just gives access to it
273	  * to add and remove runnables.
274	  * @return Returns the application runner. Do not save the
275	  * pointer past the caller's stack frame.
276	  */
277	LLRunner& getRunner() { return mRunner; }
278
279public:
280	typedef std::map<std::string, std::string> string_map;
281	string_map mOptionMap;	// Contains all command-line options and arguments in a map
282
283protected:
284
285	static void setStatus(EAppStatus status);		// Use this to change the application status.
286	static EAppStatus sStatus; // Reflects current application status
287	static BOOL sErrorThreadRunning; // Set while the error thread is running
288	static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
289
290#if !LL_WINDOWS
291	static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received.
292	typedef std::map<pid_t, LLChildInfo> child_map; // Map key is a PID
293	static child_map sChildMap;
294	static LLAppChildCallback sDefaultChildCallback;
295#endif
296
297	/**
298	  * @brief This method is called once a frame to do once a frame tasks.
299	  */
300	void stepFrame();
301
302private:
303	void startErrorThread();
304	
305	// Contains the filename of the minidump file after a crash.
306	char minidump_path[MAX_MINDUMP_PATH_LENGTH];
307
308	// *NOTE: On Windows, we need a routine to reset the structured
309	// exception handler when some evil driver has taken it over for
310	// their own purposes
311	typedef int(*signal_handler_func)(int signum);
312	static LLAppErrorHandler sErrorHandler;
313
314	// Default application threads
315	LLErrorThread* mThreadErrorp;		// Waits for app to go to status ERROR, then runs the error callback
316
317	// This is the application level runnable scheduler.
318	LLRunner mRunner;
319
320	/** @name Runtime option implementation */
321	//@{
322
323	// The application options.
324	LLSD mOptions;
325
326	// The live files for this application
327	std::vector<LLLiveFile*> mLiveFiles;
328	//@}
329
330private:
331	// the static application instance if it was created.
332	static LLApp* sApplication;
333	
334	google_breakpad::ExceptionHandler * mExceptionHandler;
335
336
337#if !LL_WINDOWS
338	friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
339#endif
340
341public:
342	static BOOL sLogInSignal;
343};
344
345#endif // LL_LLAPP_H