slplugin.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /**
  2. * @file slplugin.cpp
  3. * @brief Loader shell for plugins, intended to be launched by the plugin host application, which directly loads a plugin dynamic library.
  4. *
  5. * $LicenseInfo:firstyear=2008&license=viewergpl$
  6. *
  7. * Copyright (c) 2008-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. #include "linden_common.h"
  33. #include "llapr.h"
  34. #include "llerrorcontrol.h"
  35. #include "llpluginprocesschild.h"
  36. #include "llpluginmessage.h"
  37. #include "llstring.h"
  38. #include <iostream>
  39. #include <fstream>
  40. using namespace std;
  41. #if LL_WINDOWS
  42. # include <windows.h>
  43. #endif
  44. #if LL_DARWIN
  45. # include "slplugin-objc.h"
  46. #endif
  47. #if LL_DARWIN || LL_LINUX
  48. # include <signal.h>
  49. #endif
  50. #if LL_LINUX
  51. # include <X11/Xlib.h>
  52. #endif
  53. #if LL_DARWIN || LL_LINUX
  54. // Signal handlers to make crashes not show an OS dialog...
  55. static void crash_handler(int sig)
  56. {
  57. // Just exit cleanly. *TODO: add our own crash reporting
  58. _exit(1);
  59. }
  60. #endif
  61. #if LL_WINDOWS
  62. // Our exception handler: it will probably just exit and the host application
  63. // will miss the heartbeat and log the error in the usual fashion.
  64. LONG WINAPI myWin32ExceptionHandler(struct _EXCEPTION_POINTERS* exception_infop)
  65. {
  66. // *TODO: replace exception handler before we exit ?
  67. return EXCEPTION_EXECUTE_HANDLER;
  68. }
  69. bool checkExceptionHandler()
  70. {
  71. bool ok = true;
  72. LPTOP_LEVEL_EXCEPTION_FILTER prev_filter =
  73. SetUnhandledExceptionFilter(myWin32ExceptionHandler);
  74. if ((void*)prev_filter != (void*)myWin32ExceptionHandler)
  75. {
  76. llwarns << "Our exception handler (" << (void*)myWin32ExceptionHandler
  77. << ") replaced with " << (void*)prev_filter << "!" << llendl;
  78. ok = false;
  79. }
  80. if (!prev_filter)
  81. {
  82. ok = false;
  83. llwarns << "Our exception handler (" << (void*)myWin32ExceptionHandler
  84. << ") replaced with NULL !" << llendl;
  85. }
  86. return ok;
  87. }
  88. #endif
  89. // If this application on Windows platform is a console application, a console
  90. // is always created which is bad. Making it a Windows "application" via CMake
  91. // settings but not adding any code to explicitly create windows does the right
  92. // thing.
  93. #if LL_WINDOWS
  94. int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR cmd_line, int)
  95. #else
  96. extern "C" {
  97. int main(int argc, char** argv);
  98. }
  99. int main(int argc, char** argv)
  100. #endif
  101. {
  102. #if LL_LINUX
  103. // Ensure Xlib is started in thread-safe state
  104. XInitThreads();
  105. #endif
  106. ll_init_apr();
  107. // Set up llerror logging
  108. {
  109. LLError::initForApplication(".");
  110. LLError::setDefaultLevel(LLError::LEVEL_INFO);
  111. #if 0
  112. LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
  113. LLError::logToFile("slplugin.log");
  114. #endif
  115. }
  116. #if LL_WINDOWS
  117. if (strlen(cmd_line) == 0)
  118. {
  119. llerrs << "Usage: SLPlugin launcher_port" << llendl;
  120. }
  121. U32 port = 0;
  122. if (!LLStringUtil::convertToU32(cmd_line, port))
  123. {
  124. llerrs << "Port number must be numeric" << llendl;
  125. }
  126. // Insert our exception handler into the system so this plugin doesn't
  127. // display a crash message if something bad happens. The host app will
  128. // see the missing heartbeat and log appropriately.
  129. SetUnhandledExceptionFilter(myWin32ExceptionHandler);
  130. #elif LL_DARWIN || LL_LINUX
  131. if (argc < 2)
  132. {
  133. llerrs << "Usage: " << argv[0] << " launcher_port" << llendl;
  134. }
  135. U32 port = 0;
  136. if (!LLStringUtil::convertToU32(argv[1], port))
  137. {
  138. llerrs << "Port number must be numeric" << llendl;
  139. }
  140. // Catch signals that most kinds of crashes will generate, and exit cleanly
  141. // so the system crash dialog isn't shown.
  142. signal(SIGILL, &crash_handler); // illegal instruction
  143. signal(SIGFPE, &crash_handler); // floating-point exception
  144. signal(SIGBUS, &crash_handler); // bus error
  145. signal(SIGSEGV, &crash_handler); // segmentation violation
  146. signal(SIGSYS, &crash_handler); // non-existent system call invoked
  147. # if LL_DARWIN
  148. signal(SIGEMT, &crash_handler); // emulate instruction executed
  149. LLCocoaPlugin cocoa_interface;
  150. cocoa_interface.setupCocoa();
  151. cocoa_interface.createAutoReleasePool();
  152. # endif // LL_DARWIN
  153. #endif
  154. LLPluginProcessChild* pluginp = new LLPluginProcessChild();
  155. pluginp->init(port);
  156. #if LL_DARWIN
  157. cocoa_interface.deleteAutoReleasePool();
  158. #endif
  159. LLTimer timer;
  160. timer.start();
  161. #if LL_WINDOWS
  162. checkExceptionHandler();
  163. #endif
  164. #if LL_DARWIN && 0 // Disabled
  165. // If the plugin opens a new window (such as the Flash plugin's fullscreen
  166. // player), we may need to bring this plugin process to the foreground.
  167. // Use this to track the current frontmost window and bring this process to
  168. // the front if it changes.
  169. cocoa_interface.mEventTarget = GetEventDispatcherTarget();
  170. #endif
  171. while (!pluginp->isDone())
  172. {
  173. #if LL_DARWIN
  174. cocoa_interface.createAutoReleasePool();
  175. #endif
  176. timer.reset();
  177. pluginp->idle();
  178. #if LL_DARWIN
  179. cocoa_interface.processEvents();
  180. #endif
  181. F64 elapsed = timer.getElapsedTimeF64();
  182. F64 remaining = pluginp->getSleepTime() - elapsed;
  183. if (remaining <= 0.f)
  184. {
  185. // We have already used our full allotment. Still need to service
  186. // the network...
  187. pluginp->pump();
  188. }
  189. else
  190. {
  191. // This also services the network as needed.
  192. pluginp->sleep(remaining);
  193. }
  194. #if LL_WINDOWS && 0 // Does not appear to be required so far, even for plugins
  195. // that do crash with a single call to the intercept
  196. // exception handler.
  197. // More agressive checking of interfering exception handlers.
  198. checkExceptionHandler();
  199. #endif
  200. #if LL_DARWIN
  201. cocoa_interface.deleteAutoReleasePool();
  202. #endif
  203. }
  204. delete pluginp;
  205. ll_cleanup_apr();
  206. return 0;
  207. }