llapp.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /**
  2. * @file llapp.h
  3. * @brief Declaration of the LLApp class.
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewergpl$
  6. *
  7. * Copyright (c) 2003-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLAPP_H
  33. #define LL_LLAPP_H
  34. #include <map>
  35. #if LL_LINUX
  36. // glibc 2.16 does declare siginfo_t
  37. # define GLIBC_VERSION (__GLIBC__ * 100 + __GLIBC_MINOR__)
  38. # if GLIBC_VERSION >= 216
  39. # include <signal.h>
  40. # else
  41. typedef struct siginfo siginfo_t;
  42. # endif
  43. # undef GLIBC_VERSION
  44. #endif
  45. #include "llatomic.h"
  46. #include "llsd.h"
  47. // Forward declarations
  48. class LLErrorThread;
  49. class LLLiveFile;
  50. typedef void (*LLAppErrorHandler)();
  51. #if !LL_WINDOWS
  52. typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
  53. extern const S32 LL_SMACKDOWN_SIGNAL;
  54. extern const S32 LL_HEARTBEAT_SIGNAL;
  55. // Clear all of the signal handlers (which we want to do for the child process
  56. // when we fork
  57. void clear_signals();
  58. class LLChildInfo
  59. {
  60. public:
  61. LL_INLINE LLChildInfo()
  62. : mGotSigChild(false),
  63. mCallback(NULL)
  64. {
  65. }
  66. public:
  67. LLAppChildCallback mCallback;
  68. bool mGotSigChild;
  69. };
  70. #endif
  71. class LLApp
  72. {
  73. friend class LLErrorThread;
  74. #if !LL_WINDOWS
  75. friend void default_unix_signal_handler(int, siginfo_t*, void*);
  76. #endif
  77. protected:
  78. LOG_CLASS(LLApp);
  79. LLApp(LLErrorThread* error_thread);
  80. void commonCtor();
  81. // This method is called once a frame to do once a frame tasks.
  82. void stepFrame();
  83. public:
  84. enum EAppStatus
  85. {
  86. // No longer running: tells the error thread it can exit
  87. APP_STATUS_STOPPED,
  88. // Running: the default status
  89. APP_STATUS_RUNNING,
  90. // Quitting: threads should listen for this and clean up
  91. APP_STATUS_QUITTING,
  92. // Fatal error occurred: tells the error thread to run
  93. APP_STATUS_ERROR
  94. };
  95. LLApp();
  96. virtual ~LLApp();
  97. // Returns the static app instance if one was created.
  98. LL_INLINE static LLApp* getInstance() { return sApplication; }
  99. // Enumeration to specify option priorities in highest to
  100. enum OptionPriority
  101. {
  102. PRIORITY_RUNTIME_OVERRIDE,
  103. PRIORITY_COMMAND_LINE,
  104. PRIORITY_SPECIFIC_CONFIGURATION,
  105. PRIORITY_GENERAL_CONFIGURATION,
  106. PRIORITY_DEFAULT,
  107. PRIORITY_COUNT
  108. };
  109. // Gets the application option at the highest priority. 'name' is the name
  110. // of the option. Returns the option data or undefined when the option does
  111. // not exist.
  112. LLSD getOption(const std::string& name) const;
  113. // Parses the command line options and inserts them into the application's
  114. // command line options. The name inserted into the option will have
  115. // leading option identifiers (a minus or double minus) stripped. All
  116. // options with values will be stored as a string, while all options
  117. // without values will be stored as true. Returns true if the parse
  118. // succeeded. 'argc' and 'argv' are the parameters passed into main().
  119. bool parseCommandOptions(int argc, char** argv);
  120. // Sets the options at the specified priority. This method completely
  121. // replaces the options at the priority level with the data specified
  122. // and it will make sure level and data might be valid before doing the
  123. // replace. 'level' is the priority level of the data. 'data' is the data
  124. // to set. Returns true if the option was successfully set.
  125. bool setOptionData(OptionPriority level, LLSD data);
  126. // Gets the option data at the specified priority. This method is probably
  127. // not so useful except when merging information. 'level' is the priority
  128. // level of the data. Returns The data (if any) at the level priority.
  129. LLSD getOptionData(OptionPriority level);
  130. //
  131. // Main application logic
  132. //
  133. enum InitState
  134. {
  135. INIT_OK, // Initialization OK
  136. INIT_OK_EXIT, // Initialization OK, but do exit immediately
  137. INIT_FAILED // Initialization failed
  138. };
  139. virtual InitState init() = 0; // Override to do application initialization.
  140. // It is currently assumed that the cleanup() method will only get called
  141. // from the main thread or the error handling thread, as it will likely do
  142. // thread shutdown, among other things. Override to do application cleanup.
  143. virtual bool cleanup() = 0;
  144. // Runs the application main loop. It's assumed that when you exit this
  145. // method, the application is in one of the cleanup states, either QUITTING
  146. // or ERROR. Override for the application main loop. Needs to at least
  147. // gracefully notice the QUITTING state and exit.
  148. virtual bool mainLoop() = 0;
  149. //
  150. // Application status
  151. //
  152. // Sets status to QUITTING, the app is now shutting down
  153. static void setQuitting();
  154. // Sets status to STOPPED, the app is done running and should exit
  155. LL_INLINE static void setStopped() { sStatus = APP_STATUS_STOPPED; }
  156. // Sets status to ERROR, the error handler should run
  157. static void setError();
  158. LL_INLINE static bool isStopped() { return sStatus == APP_STATUS_STOPPED; }
  159. LL_INLINE static bool isRunning() { return sStatus == APP_STATUS_RUNNING; }
  160. LL_INLINE static bool isQuitting() { return sStatus == APP_STATUS_QUITTING; }
  161. LL_INLINE static bool isError() { return sStatus == APP_STATUS_ERROR; }
  162. // Either quitting or error (app is exiting, cleanly or not)
  163. LL_INLINE static bool isExiting() { return sStatus >= APP_STATUS_QUITTING; }
  164. #if !LL_WINDOWS
  165. static U32 getSigChildCount();
  166. static void incSigChildCount();
  167. #endif
  168. //
  169. // Error handling methods
  170. //
  171. LL_INLINE static void setErrorHandler(LLAppErrorHandler handler)
  172. {
  173. sErrorHandler = handler;
  174. }
  175. LL_INLINE static void setSyncErrorHandler(LLAppErrorHandler handler)
  176. {
  177. sSyncErrorHandler = handler;
  178. }
  179. #if !LL_WINDOWS
  180. //
  181. // Child process handling (Unix only for now)
  182. //
  183. // Sets a callback to be run on exit of a child process
  184. // WARNING ! This callback is ran from the signal handler due to Linux
  185. // threading requiring waitpid() to be called from the thread that spawned
  186. // the process.
  187. void setChildCallback(pid_t pid, LLAppChildCallback callback);
  188. // The child callback to run if no specific handler is set
  189. void setDefaultChildCallback(LLAppChildCallback callback);
  190. // Fork and do the proper signal handling/error handling mojo
  191. // WARNING: You need to make sure your signal handling callback is correct
  192. // after you fork, because not all threads are duplicated when you fork !
  193. pid_t fork();
  194. #endif
  195. protected:
  196. // Use this to change the application status.
  197. static void setStatus(S32 status);
  198. private:
  199. void startErrorThread();
  200. // Do platform-specific error-handling setup (signals, structured
  201. // exceptions).
  202. void setupErrorHandling();
  203. // Runs shortly after we detect an error, ran in the relatively robust
  204. // context of the LLErrorThread - preferred.
  205. static void runErrorHandler();
  206. // Runs IMMEDIATELY when we get an error, ran in the context of the
  207. // faulting thread.
  208. static void runSyncErrorHandler();
  209. private:
  210. // *NOTE: on Windows, we need a routine to reset the structured exception
  211. // handler when some evil driver has taken it over for their own purposes
  212. typedef int(*signal_handler_func)(int signum);
  213. static LLAppErrorHandler sErrorHandler;
  214. static LLAppErrorHandler sSyncErrorHandler;
  215. // Waits for app to go to status ERROR, then runs the error callback
  216. LLErrorThread* mThreadErrorp;
  217. // The application options.
  218. LLSD mOptions;
  219. // The static application instance if it was created.
  220. static LLApp* sApplication;
  221. protected:
  222. // Reflects the application's current status.
  223. // Made atomic since accessed from many different threads. HB
  224. static LLAtomicS32 sStatus;
  225. #if !LL_WINDOWS
  226. // Number of SIGCHLDs received.
  227. static LLAtomicU32* sSigChildCount;
  228. // Map key is a PID
  229. typedef std::map<pid_t, LLChildInfo> child_map;
  230. static child_map sChildMap;
  231. static LLAppChildCallback sDefaultChildCallback;
  232. #endif
  233. // Set while the error thread is running
  234. static bool sErrorThreadRunning;
  235. public:
  236. // Contains all command-line options and arguments in a map
  237. typedef std::map<std::string, std::string> string_map;
  238. string_map mOptionMap;
  239. static bool sLogInSignal;
  240. };
  241. #endif // LL_LLAPP_H