llapp.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. /**
  2. * @file llapp.cpp
  3. * @brief Implementation 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. #include "linden_common.h"
  33. #if !LL_WINDOWS
  34. # include <sys/wait.h> // For waitpid()
  35. #endif
  36. #include "llapp.h"
  37. #include "llcommon.h"
  38. #include "llerrorcontrol.h"
  39. #include "lleventtimer.h"
  40. #include "llevents.h"
  41. #include "llframetimer.h"
  42. #include "llmemory.h"
  43. #include "llthread.h"
  44. ///////////////////////////////////////////////////////////////////////////////
  45. // LLErrorThread class declaration (used to be in llerrorthread.h, but only
  46. // used by and with LLApp, so...)
  47. ///////////////////////////////////////////////////////////////////////////////
  48. class LLErrorThread : public LLThread
  49. {
  50. protected:
  51. LOG_CLASS(LLErrorThread);
  52. public:
  53. LLErrorThread();
  54. void run() override;
  55. void setUserData(void* user_data);
  56. void* getUserData() const;
  57. protected:
  58. void* mUserDatap; // User data associated with this thread
  59. };
  60. ///////////////////////////////////////////////////////////////////////////////
  61. // Signal handling
  62. ///////////////////////////////////////////////////////////////////////////////
  63. #if LL_WINDOWS
  64. // Windows uses structured exceptions, so it is handled a bit differently.
  65. LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS* e);
  66. BOOL ConsoleCtrlHandler(DWORD fdw_ctrl_type);
  67. #else
  68. # include <signal.h>
  69. # include <unistd.h> // for fork()
  70. void setup_signals();
  71. void default_unix_signal_handler(int signum, siginfo_t* info, void*);
  72. # if LL_DARWIN
  73. // OS-X does not support SIGRT*
  74. const S32 LL_SMACKDOWN_SIGNAL = SIGUSR1;
  75. const S32 LL_HEARTBEAT_SIGNAL = SIGUSR2;
  76. # else // Linux or (assumed) other similar unixoid
  77. // Do not catch SIGCHLD in our base application class for the viewer: some of
  78. // our 3rd party libs may need their *own* SIGCHLD handler to work. The viewer
  79. // does not need to catch SIGCHLD anyway.
  80. #define LL_IGNORE_SIGCHLD 1
  81. // We want reliable delivery of our signals: SIGRT* is it. Old LinuxThreads
  82. // versions eat SIGRTMIN+0 to SIGRTMIN+2, avoid those. Note that SIGRTMIN/
  83. // SIGRTMAX may expand to a glibc function call with a non-constant result so
  84. // these are not consts and cannot be used in constant expressions. SIGRTMAX
  85. // may return -1 on rare broken setups.
  86. const S32 LL_SMACKDOWN_SIGNAL = SIGRTMAX >= 0 ? SIGRTMAX - 1 : SIGUSR1;
  87. const S32 LL_HEARTBEAT_SIGNAL = SIGRTMAX >= 0 ? SIGRTMAX : SIGUSR2;
  88. # endif // LL_DARWIN
  89. #endif // LL_WINDOWS
  90. ///////////////////////////////////////////////////////////////////////////////
  91. // LLApp class proper
  92. ///////////////////////////////////////////////////////////////////////////////
  93. // Static variables
  94. // The static application instance
  95. LLApp* LLApp::sApplication = NULL;
  96. // Local flag for whether or not to do logging in signal handlers.
  97. bool LLApp::sLogInSignal = false;
  98. // Keeps track of application status:
  99. LLAtomicS32 LLApp::sStatus(LLApp::APP_STATUS_STOPPED);
  100. LLAppErrorHandler LLApp::sErrorHandler = NULL;
  101. LLAppErrorHandler LLApp::sSyncErrorHandler = NULL;
  102. bool LLApp::sErrorThreadRunning = false;
  103. #if !LL_WINDOWS
  104. LLApp::child_map LLApp::sChildMap;
  105. LLAtomicU32* LLApp::sSigChildCount = NULL;
  106. LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
  107. #endif
  108. LLApp::LLApp()
  109. : mThreadErrorp(NULL)
  110. {
  111. assert_main_thread(); // Make sure we record the main thread
  112. commonCtor();
  113. startErrorThread();
  114. }
  115. void LLApp::commonCtor()
  116. {
  117. // Set our status to running
  118. setStatus(APP_STATUS_RUNNING);
  119. LLCommon::initClass();
  120. #if !LL_WINDOWS
  121. // This must be initialized before the error handler.
  122. sSigChildCount = new LLAtomicU32(0);
  123. #endif
  124. // Setup error handling
  125. setupErrorHandling();
  126. // Initialize the options structure. We need to make this an array because
  127. // the structured data will not auto-allocate if we reference an invalid
  128. // location with the [] operator.
  129. mOptions = LLSD::emptyArray();
  130. LLSD sd;
  131. for (int i = 0; i < PRIORITY_COUNT; ++i)
  132. {
  133. mOptions.append(sd);
  134. }
  135. // Set the application to this instance.
  136. sApplication = this;
  137. }
  138. LLApp::LLApp(LLErrorThread* error_thread)
  139. : mThreadErrorp(error_thread)
  140. {
  141. commonCtor();
  142. }
  143. LLApp::~LLApp()
  144. {
  145. #if !LL_WINDOWS
  146. delete sSigChildCount;
  147. sSigChildCount = NULL;
  148. #endif
  149. setStopped();
  150. // *HACK: wait for the error thread to clean itself
  151. ms_sleep(100);
  152. if (mThreadErrorp)
  153. {
  154. delete mThreadErrorp;
  155. mThreadErrorp = NULL;
  156. }
  157. LLCommon::cleanupClass();
  158. }
  159. LLSD LLApp::getOption(const std::string& name) const
  160. {
  161. LLSD rv;
  162. for (LLSD::array_const_iterator iter = mOptions.beginArray(),
  163. end = mOptions.endArray();
  164. iter != end; ++iter)
  165. {
  166. rv = (*iter)[name];
  167. if (rv.isDefined())
  168. {
  169. break;
  170. }
  171. }
  172. return rv;
  173. }
  174. bool LLApp::parseCommandOptions(int argc, char** argv)
  175. {
  176. LLSD commands;
  177. std::string name;
  178. std::string value;
  179. for (S32 ii = 1; ii < argc; ++ii)
  180. {
  181. if (argv[ii][0] != '-')
  182. {
  183. llinfos << "Did not find option identifier while parsing token: "
  184. << argv[ii] << llendl;
  185. return false;
  186. }
  187. int offset = 1;
  188. if (argv[ii][1] == '-')
  189. {
  190. ++offset;
  191. }
  192. name.assign(&argv[ii][offset]);
  193. if (ii + 1 >= argc || argv[ii + 1][0] == '-')
  194. {
  195. // we found another option after this one or we have
  196. // reached the end. simply record that this option was
  197. // found and continue.
  198. int flag = name.compare("logfile");
  199. if (0 == flag)
  200. {
  201. commands[name] = "log";
  202. }
  203. else
  204. {
  205. commands[name] = true;
  206. }
  207. continue;
  208. }
  209. value.assign(argv[++ii]);
  210. #if LL_WINDOWS
  211. // Windows changed command line parsing. Deal with it.
  212. S32 slen = value.length() - 1;
  213. S32 start = 0;
  214. S32 end = slen;
  215. if (argv[ii][start] == '"')
  216. {
  217. ++start;
  218. }
  219. if (argv[ii][end] == '"')
  220. {
  221. --end;
  222. }
  223. if (start != 0 || end != slen)
  224. {
  225. value = value.substr(start, end);
  226. }
  227. #endif
  228. commands[name] = value;
  229. }
  230. setOptionData(PRIORITY_COMMAND_LINE, commands);
  231. return true;
  232. }
  233. bool LLApp::setOptionData(OptionPriority level, LLSD data)
  234. {
  235. if (level < 0 || level >= PRIORITY_COUNT || data.type() != LLSD::TypeMap)
  236. {
  237. return false;
  238. }
  239. mOptions[level] = data;
  240. return true;
  241. }
  242. LLSD LLApp::getOptionData(OptionPriority level)
  243. {
  244. if (level < 0 || level >= PRIORITY_COUNT)
  245. {
  246. return LLSD();
  247. }
  248. return mOptions[level];
  249. }
  250. void LLApp::stepFrame()
  251. {
  252. LLFrameTimer::stepFrame();
  253. LLEventTimer::stepFrame();
  254. }
  255. #if LL_WINDOWS
  256. // The following code is needed for 32-bit apps on 64-bit windows to keep it
  257. // from eating crashes. It is a lovely undocumented 'feature' in SP1 of
  258. // Windows 7. An excellent in-depth article on the issue may be found here:
  259. // http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/
  260. void EnableCrashingOnCrashes()
  261. {
  262. typedef BOOL (WINAPI* tGetPolicy)(LPDWORD lpFlags);
  263. typedef BOOL (WINAPI* tSetPolicy)(DWORD dwFlags);
  264. const DWORD EXCEPTION_SWALLOWING = 0x1;
  265. HMODULE kernel32 = LoadLibraryA("kernel32.dll");
  266. tGetPolicy pGetPolicy =
  267. (tGetPolicy)GetProcAddress(kernel32,
  268. "GetProcessUserModeExceptionPolicy");
  269. tSetPolicy pSetPolicy =
  270. (tSetPolicy)GetProcAddress(kernel32,
  271. "SetProcessUserModeExceptionPolicy");
  272. if (pGetPolicy && pSetPolicy)
  273. {
  274. DWORD dwFlags;
  275. if (pGetPolicy(&dwFlags))
  276. {
  277. // Turn off the filter
  278. pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
  279. }
  280. }
  281. }
  282. #endif
  283. // Error handling is done by starting up an error handling thread, which just
  284. // sleeps and occasionally checks to see if the app is in an error state, and
  285. // sees if it needs to be run.
  286. void LLApp::setupErrorHandling()
  287. {
  288. #if LL_WINDOWS
  289. // Windows does not have the same signal handling mechanisms as UNIX. What
  290. // we do is install an unhandled exception handler, which will try to do
  291. // the right thing in the case of an error (generate a minidump).
  292. EnableCrashingOnCrashes();
  293. // This sets a callback to handle w32 signals to the console window. The
  294. // viewer should not be affected, since its a windowed app.
  295. SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleCtrlHandler, TRUE);
  296. #else
  297. // Start up signal handling.
  298. //
  299. // There are two different classes of signals. Synchronous signals are
  300. // delivered to a specific thread, asynchronous signals can be delivered to
  301. // any thread (in theory)
  302. setup_signals();
  303. #endif
  304. }
  305. // Starts the error handling thread, which is responsible for taking action
  306. // when the app goes into the APP_STATUS_ERROR state
  307. void LLApp::startErrorThread()
  308. {
  309. llinfos << "Starting error thread" << llendl;
  310. mThreadErrorp = new LLErrorThread();
  311. mThreadErrorp->setUserData((void*)this);
  312. mThreadErrorp->start();
  313. }
  314. //static
  315. void LLApp::runSyncErrorHandler()
  316. {
  317. if (sSyncErrorHandler)
  318. {
  319. sSyncErrorHandler();
  320. }
  321. }
  322. //static
  323. void LLApp::runErrorHandler()
  324. {
  325. if (sErrorHandler)
  326. {
  327. sErrorHandler();
  328. }
  329. setStatus(APP_STATUS_STOPPED);
  330. }
  331. //static
  332. void LLApp::setError()
  333. {
  334. if (!isError())
  335. {
  336. // Perform any needed synchronous error-handling
  337. runSyncErrorHandler();
  338. // Set app status to ERROR so that the LLErrorThread notices
  339. setStatus(APP_STATUS_ERROR);
  340. }
  341. }
  342. //static
  343. void LLApp::setQuitting()
  344. {
  345. if (!isExiting())
  346. {
  347. // If we are already exiting, we do not want to reset our state back to
  348. // quitting.
  349. llinfos << "Setting app state to QUITTING" << llendl;
  350. setStatus(APP_STATUS_QUITTING);
  351. }
  352. }
  353. //static
  354. void LLApp::setStatus(S32 status)
  355. {
  356. sStatus = status;
  357. // This can also happen very late in the application lifecycle; do not
  358. // resurrect a deleted LLSingleton...
  359. if (LLEventPumps::destroyed())
  360. {
  361. return;
  362. }
  363. // Notify interested parties of status change
  364. LLSD value;
  365. switch (status)
  366. {
  367. case APP_STATUS_STOPPED:
  368. value = LLSD::String("stopped");
  369. break;
  370. case APP_STATUS_RUNNING:
  371. value = LLSD::String("running");
  372. break;
  373. case APP_STATUS_QUITTING:
  374. value = LLSD::String("quitting");
  375. break;
  376. case APP_STATUS_ERROR:
  377. value = LLSD::String("error");
  378. break;
  379. default:
  380. value = LLSD::Integer(status);
  381. }
  382. LLSD data;
  383. data["status"] = value;
  384. gEventPumps.obtain("LLApp").post(data);
  385. }
  386. #if !LL_WINDOWS
  387. //static
  388. U32 LLApp::getSigChildCount()
  389. {
  390. if (sSigChildCount)
  391. {
  392. return U32(*sSigChildCount);
  393. }
  394. return 0;
  395. }
  396. //static
  397. void LLApp::incSigChildCount()
  398. {
  399. if (sSigChildCount)
  400. {
  401. ++(*sSigChildCount);
  402. }
  403. }
  404. #endif
  405. #if LL_WINDOWS
  406. // Translates the signals/exceptions into cross-platform stuff Windows
  407. // implementation
  408. LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS*)
  409. {
  410. // Make sure the user sees something to indicate that the app crashed.
  411. LONG retval = EXCEPTION_EXECUTE_HANDLER;
  412. if (LLApp::isError())
  413. {
  414. llwarns << "Got another fatal signal while in the error handler, die now !"
  415. << llendl;
  416. return retval;
  417. }
  418. // Flag status to error, so thread_error starts its work
  419. LLApp::setError();
  420. // Block in the exception handler until the app has stopped. This is pretty
  421. // sketchy, but appears to work just fine
  422. while (!LLApp::isStopped())
  423. {
  424. ms_sleep(10);
  425. }
  426. // *TODO: generate a minidump if we can. This needs to be ported over from
  427. // the viewer-specific LLWinDebug class
  428. // At this point, we always want to exit the app. There is no graceful
  429. // recovery for an unhandled exception. Just kill the process.
  430. return retval;
  431. }
  432. // Win32 does not support signals. This is used instead.
  433. BOOL ConsoleCtrlHandler(DWORD fdw_ctrl_type)
  434. {
  435. switch (fdw_ctrl_type)
  436. {
  437. // For these, just set our state to quitting, not error
  438. case CTRL_BREAK_EVENT:
  439. case CTRL_LOGOFF_EVENT:
  440. case CTRL_SHUTDOWN_EVENT:
  441. case CTRL_CLOSE_EVENT: // From end task or the window close button.
  442. case CTRL_C_EVENT: // from CTRL-C on the keyboard
  443. if (LLApp::isExiting())
  444. {
  445. // We are already trying to die, just ignore this signal
  446. if (LLApp::sLogInSignal)
  447. {
  448. llinfos << "Already trying to quit, ignoring signal !"
  449. << llendl;
  450. }
  451. return TRUE;
  452. }
  453. LLApp::setQuitting();
  454. return TRUE;
  455. default:
  456. return FALSE;
  457. }
  458. }
  459. #else
  460. void LLApp::setChildCallback(pid_t pid, LLAppChildCallback callback)
  461. {
  462. LLChildInfo child_info;
  463. child_info.mCallback = callback;
  464. LLApp::sChildMap[pid] = child_info;
  465. }
  466. void LLApp::setDefaultChildCallback(LLAppChildCallback callback)
  467. {
  468. LLApp::sDefaultChildCallback = callback;
  469. }
  470. pid_t LLApp::fork()
  471. {
  472. fflush(NULL); // flush all buffers before the child inherits them
  473. pid_t pid = ::fork();
  474. if (pid < 0)
  475. {
  476. int system_error = errno;
  477. llwarns << "Unable to fork ! Operating system error code: "
  478. << system_error << llendl;
  479. }
  480. else if (pid == 0)
  481. {
  482. // Sleep a bit to allow the parent to set up child callbacks.
  483. ms_sleep(10);
  484. // We need to disable signal handling, because we don't have a signal
  485. // handling thread anymore.
  486. setupErrorHandling();
  487. }
  488. else
  489. {
  490. llinfos << "Forked child process " << pid << llendl;
  491. }
  492. return pid;
  493. }
  494. void setup_signals()
  495. {
  496. // Set up signal handlers that may result in program termination
  497. struct sigaction act;
  498. act.sa_sigaction = default_unix_signal_handler;
  499. sigemptyset(&act.sa_mask);
  500. act.sa_flags = SA_SIGINFO;
  501. // Synchronous signals
  502. sigaction(SIGABRT, &act, NULL);
  503. sigaction(SIGALRM, &act, NULL);
  504. sigaction(SIGBUS, &act, NULL);
  505. sigaction(SIGFPE, &act, NULL);
  506. sigaction(SIGILL, &act, NULL);
  507. sigaction(SIGPIPE, &act, NULL);
  508. sigaction(SIGSEGV, &act, NULL);
  509. sigaction(SIGSYS, &act, NULL);
  510. sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL);
  511. sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL);
  512. // Asynchronous signals that are normally ignored
  513. #ifndef LL_IGNORE_SIGCHLD
  514. sigaction(SIGCHLD, &act, NULL);
  515. #endif // LL_IGNORE_SIGCHLD
  516. sigaction(SIGUSR2, &act, NULL);
  517. // Asynchronous signals that result in attempted graceful exit
  518. sigaction(SIGHUP, &act, NULL);
  519. sigaction(SIGTERM, &act, NULL);
  520. sigaction(SIGINT, &act, NULL);
  521. // Asynchronous signals that result in core
  522. sigaction(SIGQUIT, &act, NULL);
  523. }
  524. void clear_signals()
  525. {
  526. struct sigaction act;
  527. act.sa_handler = SIG_DFL;
  528. sigemptyset(&act.sa_mask);
  529. act.sa_flags = SA_SIGINFO;
  530. // Synchronous signals
  531. sigaction(SIGABRT, &act, NULL);
  532. sigaction(SIGALRM, &act, NULL);
  533. sigaction(SIGBUS, &act, NULL);
  534. sigaction(SIGFPE, &act, NULL);
  535. sigaction(SIGILL, &act, NULL);
  536. sigaction(SIGPIPE, &act, NULL);
  537. sigaction(SIGSEGV, &act, NULL);
  538. sigaction(SIGSYS, &act, NULL);
  539. sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL);
  540. sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL);
  541. // Asynchronous signals that are normally ignored
  542. #ifndef LL_IGNORE_SIGCHLD
  543. sigaction(SIGCHLD, &act, NULL);
  544. #endif // LL_IGNORE_SIGCHLD
  545. // Asynchronous signals that result in attempted graceful exit
  546. sigaction(SIGHUP, &act, NULL);
  547. sigaction(SIGTERM, &act, NULL);
  548. sigaction(SIGINT, &act, NULL);
  549. // Asynchronous signals that result in core
  550. sigaction(SIGUSR2, &act, NULL);
  551. sigaction(SIGQUIT, &act, NULL);
  552. }
  553. // Unix implementation of synchronous signal handler. This runs in the thread
  554. // that threw the signal. We do the somewhat sketchy operation of blocking in
  555. // here until the error handler has gracefully stopped the app.
  556. void default_unix_signal_handler(int signum, siginfo_t* info, void*)
  557. {
  558. if (LLApp::sLogInSignal)
  559. {
  560. llinfos << "Got signal " << signum << llendl;
  561. }
  562. switch (signum)
  563. {
  564. case SIGCHLD:
  565. if (LLApp::sLogInSignal)
  566. {
  567. llinfos << "Got SIGCHLD from " << info->si_pid << llendl;
  568. }
  569. // Check result code for all childs for which we have registered
  570. // callbacks THIS WILL NOT WORK IF SIGCHLD IS SENT without killing
  571. // the child.
  572. // *TODO: now that we are using SIGACTION, we could actually
  573. // implement the launcher behavior to determine who sent the
  574. // SIGCHLD even if it does not result in child termination
  575. if (LLApp::sChildMap.count(info->si_pid))
  576. {
  577. LLApp::sChildMap[info->si_pid].mGotSigChild = true;
  578. }
  579. LLApp::incSigChildCount();
  580. return;
  581. case SIGABRT:
  582. // Abort just results in termination of the app, no funky error
  583. // handling.
  584. if (LLApp::sLogInSignal)
  585. {
  586. llwarns << "Got SIGABRT, terminating" << llendl;
  587. }
  588. clear_signals();
  589. raise(signum);
  590. return;
  591. case SIGINT:
  592. #if !LL_DARWIN
  593. case SIGHUP:
  594. #endif
  595. case SIGTERM:
  596. if (LLApp::sLogInSignal)
  597. {
  598. #if LL_DARWIN
  599. llwarns << "Got SIGINT or SIGTERM, exiting gracefully"
  600. << llendl;
  601. #else
  602. llwarns << "Got SIGINT, SIGHUP or SIGTERM, exiting gracefully"
  603. << llendl;
  604. #endif
  605. }
  606. // Graceful exit... Just set our state to quitting, not error.
  607. if (LLApp::isExiting())
  608. {
  609. // We are already trying to die, just ignore this signal
  610. if (LLApp::sLogInSignal)
  611. {
  612. llinfos << "Already trying to quit, ignoring signal !"
  613. << llendl;
  614. }
  615. return;
  616. }
  617. LLApp::setQuitting();
  618. return;
  619. case SIGALRM:
  620. case SIGPIPE:
  621. case SIGUSR2:
  622. default:
  623. if (signum == LL_SMACKDOWN_SIGNAL || signum == SIGBUS ||
  624. signum == SIGILL || signum == SIGFPE || signum == SIGSEGV ||
  625. signum == SIGQUIT)
  626. {
  627. if (signum == LL_SMACKDOWN_SIGNAL)
  628. {
  629. // Smackdown treated just like any other app termination,
  630. // for now
  631. if (LLApp::sLogInSignal)
  632. {
  633. llwarns << "Handling smackdown signal !" << llendl;
  634. }
  635. else
  636. {
  637. // Do not log anything, even errors: this is because
  638. // this signal could happen anywhere.
  639. LLError::setDefaultLevel(LLError::LEVEL_NONE);
  640. }
  641. // Change the signal that we re-raise to SIGABRT, so we
  642. // generate a core dump.
  643. signum = SIGABRT;
  644. }
  645. if (LLApp::sLogInSignal)
  646. {
  647. llwarns << "Handling fatal signal !" << llendl;
  648. }
  649. if (LLApp::isError())
  650. {
  651. // Received second fatal signal while handling first, just
  652. // die right now. Set the signal handlers back to default
  653. // before handling the signal: this makes the next signal
  654. // wipe out the app.
  655. clear_signals();
  656. if (LLApp::sLogInSignal)
  657. {
  658. llwarns << "Got another fatal signal while in the error handler, die now !"
  659. << llendl;
  660. }
  661. raise(signum);
  662. return;
  663. }
  664. if (LLApp::sLogInSignal)
  665. {
  666. llwarns << "Flagging error status and waiting for shutdown"
  667. << llendl;
  668. }
  669. // Flag status to ERROR, so thread_error does its work.
  670. LLApp::setError();
  671. // Block in the signal handler until somebody says that we are done.
  672. while (LLApp::sErrorThreadRunning && !LLApp::isStopped())
  673. {
  674. ms_sleep(10);
  675. }
  676. if (LLApp::sLogInSignal)
  677. {
  678. llwarns << "App is stopped, re-raising signal" << llendl;
  679. }
  680. clear_signals();
  681. raise(signum);
  682. return;
  683. }
  684. else if (LLApp::sLogInSignal)
  685. {
  686. llinfos << "Unhandled signal " << signum << ", ignoring !"
  687. << llendl;
  688. }
  689. }
  690. }
  691. #endif
  692. ///////////////////////////////////////////////////////////////////////////////
  693. // LLErrorThread class (used to be in llerrorthread.cpp, but only used by and
  694. // with LLApp, so...)
  695. ///////////////////////////////////////////////////////////////////////////////
  696. LLErrorThread::LLErrorThread()
  697. : LLThread("Error"),
  698. mUserDatap(NULL)
  699. {
  700. }
  701. void LLErrorThread::setUserData(void* user_data)
  702. {
  703. mUserDatap = user_data;
  704. }
  705. void* LLErrorThread::getUserData() const
  706. {
  707. return mUserDatap;
  708. }
  709. #if !LL_WINDOWS
  710. //
  711. // Various signal/error handling functions that can't be put into the class
  712. //
  713. void get_child_status(const int waitpid_status, int& process_status,
  714. bool& exited, bool do_logging)
  715. {
  716. exited = false;
  717. process_status = -1;
  718. // The child process exited. Call its callback, and then clean it up
  719. if (WIFEXITED(waitpid_status))
  720. {
  721. process_status = WEXITSTATUS(waitpid_status);
  722. exited = true;
  723. if (do_logging)
  724. {
  725. llinfos << "get_child_status - Child exited cleanly with return of "
  726. << process_status << llendl;
  727. }
  728. return;
  729. }
  730. else if (WIFSIGNALED(waitpid_status))
  731. {
  732. process_status = WTERMSIG(waitpid_status);
  733. exited = true;
  734. if (do_logging)
  735. {
  736. llinfos << "get_child_status - Child died because of uncaught signal "
  737. << process_status << llendl;
  738. #ifdef WCOREDUMP
  739. if (WCOREDUMP(waitpid_status))
  740. {
  741. llinfos << "get_child_status - Child dumped core" << llendl;
  742. }
  743. else
  744. {
  745. llinfos << "get_child_status - Child didn't dump core"
  746. << llendl;
  747. }
  748. #endif
  749. }
  750. return;
  751. }
  752. else if (do_logging)
  753. {
  754. // This is weird. I just dump the waitpid status into the status code,
  755. // not that there's any way of telling what it is...
  756. llinfos << "get_child_status - Got SIGCHILD but child didn't exit"
  757. << llendl;
  758. process_status = waitpid_status;
  759. }
  760. }
  761. #endif
  762. void LLErrorThread::run()
  763. {
  764. LLApp::sErrorThreadRunning = true;
  765. // This thread sits and waits for the sole purpose
  766. // of waiting for the signal/exception handlers to flag the
  767. // application state as APP_STATUS_ERROR.
  768. llinfos << "thread_error - Waiting for an error" << llendl;
  769. #if !LL_WINDOWS
  770. U32 last_sig_child_count = 0;
  771. #endif
  772. while (true)
  773. {
  774. if (LLApp::isError() || LLApp::isStopped())
  775. {
  776. // The application has stopped running, time to take action (maybe)
  777. break;
  778. }
  779. #if !LL_WINDOWS
  780. // Check whether or not the main thread had a sig child we have not
  781. // handled.
  782. U32 current_sig_child_count = LLApp::getSigChildCount();
  783. if (last_sig_child_count != current_sig_child_count)
  784. {
  785. int status = 0;
  786. pid_t child_pid = 0;
  787. last_sig_child_count = current_sig_child_count;
  788. if (LLApp::sLogInSignal)
  789. {
  790. llinfos << "thread_error handling SIGCHLD #"
  791. << current_sig_child_count << llendl;
  792. }
  793. for (LLApp::child_map::iterator iter = LLApp::sChildMap.begin();
  794. iter != LLApp::sChildMap.end(); )
  795. {
  796. child_pid = iter->first;
  797. LLChildInfo &child_info = iter->second;
  798. // Check the status of *all* children, in case we missed a
  799. // signal
  800. if (waitpid(child_pid, &status, WNOHANG) != 0)
  801. {
  802. bool exited = false;
  803. int exit_status = -1;
  804. get_child_status(status, exit_status, exited,
  805. LLApp::sLogInSignal);
  806. if (child_info.mCallback)
  807. {
  808. if (LLApp::sLogInSignal)
  809. {
  810. llinfos << "Running child callback" << llendl;
  811. }
  812. child_info.mCallback(child_pid, exited, status);
  813. }
  814. LLApp::sChildMap.erase(iter++);
  815. }
  816. else
  817. {
  818. // Child did not terminate, yet we got a sigchild somewhere
  819. if (child_info.mGotSigChild && child_info.mCallback)
  820. {
  821. child_info.mCallback(child_pid, false, 0);
  822. }
  823. child_info.mGotSigChild = false;
  824. ++iter;
  825. }
  826. }
  827. // Check the status of *all* children, in case we missed a signal
  828. // Same as above, but use the default child callback
  829. while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0)
  830. {
  831. if (waitpid(child_pid, &status, WNOHANG) != 0)
  832. {
  833. bool exited = false;
  834. int exit_status = -1;
  835. get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
  836. if (LLApp::sDefaultChildCallback)
  837. {
  838. if (LLApp::sLogInSignal)
  839. {
  840. llinfos << "Running default child callback"
  841. << llendl;
  842. }
  843. LLApp::sDefaultChildCallback(child_pid, true, status);
  844. }
  845. }
  846. }
  847. }
  848. #endif
  849. ms_sleep(10);
  850. }
  851. if (LLApp::isError())
  852. {
  853. // The app is in an error state, run the application's error handler.
  854. #if 0
  855. llinfos << "thread_error - An error has occurred, running error callback !"
  856. << llendl;
  857. #endif
  858. // Run the error handling callback
  859. LLApp::runErrorHandler();
  860. }
  861. #if 0
  862. else
  863. {
  864. // Everything is okay, a clean exit.
  865. llinfos << "thread_error - Application exited cleanly" << llendl;
  866. }
  867. llinfos << "thread_error - Exiting" << llendl;
  868. #endif
  869. LLApp::sErrorThreadRunning = false;
  870. }