PageRenderTime 51ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llappviewer.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2191 lines | 1448 code | 399 blank | 344 comment | 149 complexity | 2d022bdd69b86b347004945c8eb65f14 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llappviewer.cpp
  3. * @brief The LLAppViewer class definitions
  4. *
  5. * $LicenseInfo:firstyear=2007&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. #include "llviewerprecompiledheaders.h"
  27. #include "llappviewer.h"
  28. // Viewer includes
  29. #include "llversioninfo.h"
  30. #include "llversionviewer.h"
  31. #include "llfeaturemanager.h"
  32. #include "lluictrlfactory.h"
  33. #include "lltexteditor.h"
  34. #include "llerrorcontrol.h"
  35. #include "lleventtimer.h"
  36. #include "llviewertexturelist.h"
  37. #include "llgroupmgr.h"
  38. #include "llagent.h"
  39. #include "llagentcamera.h"
  40. #include "llagentlanguage.h"
  41. #include "llagentwearables.h"
  42. #include "llwindow.h"
  43. #include "llviewerstats.h"
  44. #include "llviewerstatsrecorder.h"
  45. #include "llmarketplacefunctions.h"
  46. #include "llmarketplacenotifications.h"
  47. #include "llmd5.h"
  48. #include "llmeshrepository.h"
  49. #include "llpumpio.h"
  50. #include "llmimetypes.h"
  51. #include "llslurl.h"
  52. #include "llstartup.h"
  53. #include "llfocusmgr.h"
  54. #include "llviewerjoystick.h"
  55. #include "llallocator.h"
  56. #include "llares.h"
  57. #include "llcurl.h"
  58. #include "llcalc.h"
  59. #include "lltexturestats.h"
  60. #include "lltexturestats.h"
  61. #include "llviewerwindow.h"
  62. #include "llviewerdisplay.h"
  63. #include "llviewermedia.h"
  64. #include "llviewerparcelmedia.h"
  65. #include "llviewermediafocus.h"
  66. #include "llviewermessage.h"
  67. #include "llviewerobjectlist.h"
  68. #include "llworldmap.h"
  69. #include "llmutelist.h"
  70. #include "llviewerhelp.h"
  71. #include "lluicolortable.h"
  72. #include "llurldispatcher.h"
  73. #include "llurlhistory.h"
  74. //#include "llfirstuse.h"
  75. #include "llrender.h"
  76. #include "llteleporthistory.h"
  77. #include "lltoast.h"
  78. #include "lllocationhistory.h"
  79. #include "llfasttimerview.h"
  80. #include "llvector4a.h"
  81. #include "llviewermenufile.h"
  82. #include "llvoicechannel.h"
  83. #include "llvoavatarself.h"
  84. #include "llurlmatch.h"
  85. #include "lltextutil.h"
  86. #include "lllogininstance.h"
  87. #include "llprogressview.h"
  88. #include "llvocache.h"
  89. #include "llweb.h"
  90. #include "llsecondlifeurls.h"
  91. #include "llupdaterservice.h"
  92. #include "llcallfloater.h"
  93. // Linden library includes
  94. #include "llavatarnamecache.h"
  95. #include "lldiriterator.h"
  96. #include "llimagej2c.h"
  97. #include "llmemory.h"
  98. #include "llprimitive.h"
  99. #include "llurlaction.h"
  100. #include "llurlentry.h"
  101. #include "llvfile.h"
  102. #include "llvfsthread.h"
  103. #include "llvolumemgr.h"
  104. #include "llxfermanager.h"
  105. #include "llnotificationmanager.h"
  106. #include "llnotifications.h"
  107. #include "llnotificationsutil.h"
  108. // Third party library includes
  109. #include <boost/bind.hpp>
  110. #include <boost/foreach.hpp>
  111. #if LL_WINDOWS
  112. # include <share.h> // For _SH_DENYWR in initMarkerFile
  113. #else
  114. # include <sys/file.h> // For initMarkerFile support
  115. #endif
  116. #include "llapr.h"
  117. #include "apr_dso.h"
  118. #include <boost/lexical_cast.hpp>
  119. #include "llviewerkeyboard.h"
  120. #include "lllfsthread.h"
  121. #include "llworkerthread.h"
  122. #include "lltexturecache.h"
  123. #include "lltexturefetch.h"
  124. #include "llimageworker.h"
  125. #include "llevents.h"
  126. // The files below handle dependencies from cleanup.
  127. #include "llkeyframemotion.h"
  128. #include "llworldmap.h"
  129. #include "llhudmanager.h"
  130. #include "lltoolmgr.h"
  131. #include "llassetstorage.h"
  132. #include "llpolymesh.h"
  133. #include "llproxy.h"
  134. #include "llaudioengine.h"
  135. #include "llstreamingaudio.h"
  136. #include "llviewermenu.h"
  137. #include "llselectmgr.h"
  138. #include "lltrans.h"
  139. #include "lltransutil.h"
  140. #include "lltracker.h"
  141. #include "llviewerparcelmgr.h"
  142. #include "llworldmapview.h"
  143. #include "llpostprocess.h"
  144. #include "llwlparammanager.h"
  145. #include "llwaterparammanager.h"
  146. #include "lldebugview.h"
  147. #include "llconsole.h"
  148. #include "llcontainerview.h"
  149. #include "lltooltip.h"
  150. #include "llsdserialize.h"
  151. #include "llworld.h"
  152. #include "llhudeffecttrail.h"
  153. #include "llvectorperfoptions.h"
  154. #include "llslurl.h"
  155. #include "llwatchdog.h"
  156. // Included so that constants/settings might be initialized
  157. // in save_settings_to_globals()
  158. #include "llbutton.h"
  159. #include "llstatusbar.h"
  160. #include "llsurface.h"
  161. #include "llvosky.h"
  162. #include "llvotree.h"
  163. #include "llvoavatar.h"
  164. #include "llfolderview.h"
  165. #include "llagentpilot.h"
  166. #include "llvovolume.h"
  167. #include "llflexibleobject.h"
  168. #include "llvosurfacepatch.h"
  169. #include "llviewerfloaterreg.h"
  170. #include "llcommandlineparser.h"
  171. #include "llfloatermemleak.h"
  172. #include "llfloaterreg.h"
  173. #include "llfloatersnapshot.h"
  174. #include "llfloaterinventory.h"
  175. // includes for idle() idleShutdown()
  176. #include "llviewercontrol.h"
  177. #include "lleventnotifier.h"
  178. #include "llcallbacklist.h"
  179. #include "pipeline.h"
  180. #include "llgesturemgr.h"
  181. #include "llsky.h"
  182. #include "llvlmanager.h"
  183. #include "llviewercamera.h"
  184. #include "lldrawpoolbump.h"
  185. #include "llvieweraudio.h"
  186. #include "llimview.h"
  187. #include "llviewerthrottle.h"
  188. #include "llparcel.h"
  189. #include "llavatariconctrl.h"
  190. #include "llgroupiconctrl.h"
  191. #include "llviewerassetstats.h"
  192. // Include for security api initialization
  193. #include "llsecapi.h"
  194. #include "llmachineid.h"
  195. #include "llmainlooprepeater.h"
  196. // *FIX: These extern globals should be cleaned up.
  197. // The globals either represent state/config/resource-storage of either
  198. // this app, or another 'component' of the viewer. App globals should be
  199. // moved into the app class, where as the other globals should be
  200. // moved out of here.
  201. // If a global symbol reference seems valid, it will be included
  202. // via header files above.
  203. //----------------------------------------------------------------------------
  204. // llviewernetwork.h
  205. #include "llviewernetwork.h"
  206. // define a self-registering event API object
  207. #include "llappviewerlistener.h"
  208. #if (LL_LINUX || LL_SOLARIS) && LL_GTK
  209. #include "glib.h"
  210. #endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
  211. #if LL_MSVC
  212. // disable boost::lexical_cast warning
  213. #pragma warning (disable:4702)
  214. #endif
  215. static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
  216. ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
  217. //
  218. //----------------------------------------------------------------------------
  219. // viewer.cpp - these are only used in viewer, should be easily moved.
  220. #if LL_DARWIN
  221. extern void init_apple_menu(const char* product);
  222. #endif // LL_DARWIN
  223. extern BOOL gRandomizeFramerate;
  224. extern BOOL gPeriodicSlowFrame;
  225. extern BOOL gDebugGL;
  226. ////////////////////////////////////////////////////////////
  227. // All from the last globals push...
  228. F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
  229. F32 gSimFrames;
  230. BOOL gShowObjectUpdates = FALSE;
  231. BOOL gUseQuickTime = TRUE;
  232. eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
  233. LLSD gDebugInfo;
  234. U32 gFrameCount = 0;
  235. U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
  236. LLPumpIO* gServicePump = NULL;
  237. U64 gFrameTime = 0;
  238. F32 gFrameTimeSeconds = 0.f;
  239. F32 gFrameIntervalSeconds = 0.f;
  240. F32 gFPSClamped = 10.f; // Pretend we start at target rate.
  241. F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets
  242. U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
  243. U32 gFrameStalls = 0;
  244. const F64 FRAME_STALL_THRESHOLD = 1.0;
  245. LLTimer gRenderStartTime;
  246. LLFrameTimer gForegroundTime;
  247. LLFrameTimer gLoggedInTime;
  248. LLTimer gLogoutTimer;
  249. static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg.
  250. F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
  251. BOOL gDisconnected = FALSE;
  252. // used to restore texture state after a mode switch
  253. LLFrameTimer gRestoreGLTimer;
  254. BOOL gRestoreGL = FALSE;
  255. BOOL gUseWireframe = FALSE;
  256. // VFS globals - see llappviewer.h
  257. LLVFS* gStaticVFS = NULL;
  258. LLMemoryInfo gSysMemory;
  259. U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp
  260. std::string gLastVersionChannel;
  261. LLVector3 gWindVec(3.0, 3.0, 0.0);
  262. LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
  263. U32 gPacketsIn = 0;
  264. BOOL gPrintMessagesThisFrame = FALSE;
  265. BOOL gRandomizeFramerate = FALSE;
  266. BOOL gPeriodicSlowFrame = FALSE;
  267. BOOL gCrashOnStartup = FALSE;
  268. BOOL gLLErrorActivated = FALSE;
  269. BOOL gLogoutInProgress = FALSE;
  270. ////////////////////////////////////////////////////////////
  271. // Internal globals... that should be removed.
  272. static std::string gArgs;
  273. const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
  274. const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
  275. const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
  276. const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
  277. static BOOL gDoDisconnect = FALSE;
  278. static std::string gLaunchFileOnQuit;
  279. // Used on Win32 for other apps to identify our window (eg, win_setup)
  280. const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
  281. //-- LLDeferredTaskList ------------------------------------------------------
  282. /**
  283. * A list of deferred tasks.
  284. *
  285. * We sometimes need to defer execution of some code until the viewer gets idle,
  286. * e.g. removing an inventory item from within notifyObservers() may not work out.
  287. *
  288. * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration.
  289. * All tasks are executed only once.
  290. */
  291. class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList>
  292. {
  293. LOG_CLASS(LLDeferredTaskList);
  294. friend class LLAppViewer;
  295. typedef boost::signals2::signal<void()> signal_t;
  296. void addTask(const signal_t::slot_type& cb)
  297. {
  298. mSignal.connect(cb);
  299. }
  300. void run()
  301. {
  302. if (!mSignal.empty())
  303. {
  304. mSignal();
  305. mSignal.disconnect_all_slots();
  306. }
  307. }
  308. signal_t mSignal;
  309. };
  310. //----------------------------------------------------------------------------
  311. // List of entries from strings.xml to always replace
  312. static std::set<std::string> default_trans_args;
  313. void init_default_trans_args()
  314. {
  315. default_trans_args.insert("SECOND_LIFE"); // World
  316. default_trans_args.insert("APP_NAME");
  317. default_trans_args.insert("CAPITALIZED_APP_NAME");
  318. default_trans_args.insert("SECOND_LIFE_GRID");
  319. default_trans_args.insert("SUPPORT_SITE");
  320. }
  321. //----------------------------------------------------------------------------
  322. // File scope definitons
  323. const char *VFS_DATA_FILE_BASE = "data.db2.x.";
  324. const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
  325. struct SettingsFile : public LLInitParam::Block<SettingsFile>
  326. {
  327. Mandatory<std::string> name;
  328. Optional<std::string> file_name;
  329. Optional<bool> required,
  330. persistent;
  331. Optional<std::string> file_name_setting;
  332. SettingsFile()
  333. : name("name"),
  334. file_name("file_name"),
  335. required("required", false),
  336. persistent("persistent", true),
  337. file_name_setting("file_name_setting")
  338. {}
  339. };
  340. struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
  341. {
  342. Mandatory<std::string> name;
  343. Mandatory<S32> path_index;
  344. Multiple<SettingsFile> files;
  345. SettingsGroup()
  346. : name("name"),
  347. path_index("path_index"),
  348. files("file")
  349. {}
  350. };
  351. struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
  352. {
  353. Multiple<SettingsGroup> groups;
  354. SettingsFiles()
  355. : groups("group")
  356. {}
  357. };
  358. static std::string gWindowTitle;
  359. LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
  360. //----------------------------------------------------------------------------
  361. // Metrics logging control constants
  362. //----------------------------------------------------------------------------
  363. static const F32 METRICS_INTERVAL_DEFAULT = 600.0;
  364. static const F32 METRICS_INTERVAL_QA = 30.0;
  365. static F32 app_metrics_interval = METRICS_INTERVAL_DEFAULT;
  366. static bool app_metrics_qa_mode = false;
  367. void idle_afk_check()
  368. {
  369. // check idle timers
  370. F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
  371. F32 afk_timeout = gSavedSettings.getS32("AFKTimeout");
  372. if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK())
  373. {
  374. LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
  375. gAgent.setAFK();
  376. }
  377. }
  378. // A callback set in LLAppViewer::init()
  379. static void ui_audio_callback(const LLUUID& uuid)
  380. {
  381. if (gAudiop)
  382. {
  383. gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
  384. }
  385. }
  386. bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
  387. {
  388. if(!match || !base || base->getPlainText())
  389. return false;
  390. LLUUID match_id = match->getID();
  391. LLIconCtrl* icon;
  392. if(gAgent.isInGroup(match_id, TRUE))
  393. {
  394. LLGroupIconCtrl::Params icon_params;
  395. icon_params.group_id = match_id;
  396. icon_params.rect = LLRect(0, 16, 16, 0);
  397. icon_params.visible = true;
  398. icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
  399. }
  400. else
  401. {
  402. LLAvatarIconCtrl::Params icon_params;
  403. icon_params.avatar_id = match_id;
  404. icon_params.rect = LLRect(0, 16, 16, 0);
  405. icon_params.visible = true;
  406. icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
  407. }
  408. LLInlineViewSegment::Params params;
  409. params.force_newline = false;
  410. params.view = icon;
  411. params.left_pad = 4;
  412. params.right_pad = 4;
  413. params.top_pad = -2;
  414. params.bottom_pad = 2;
  415. base->appendWidget(params," ",false);
  416. return true;
  417. }
  418. void request_initial_instant_messages()
  419. {
  420. static BOOL requested = FALSE;
  421. if (!requested
  422. && gMessageSystem
  423. && LLMuteList::getInstance()->isLoaded()
  424. && isAgentAvatarValid())
  425. {
  426. // Auto-accepted inventory items may require the avatar object
  427. // to build a correct name. Likewise, inventory offers from
  428. // muted avatars require the mute list to properly mute.
  429. LLMessageSystem* msg = gMessageSystem;
  430. msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
  431. msg->nextBlockFast(_PREHASH_AgentData);
  432. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  433. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  434. gAgent.sendReliableMessage();
  435. requested = TRUE;
  436. }
  437. }
  438. // Use these strictly for things that are constructed at startup,
  439. // or for things that are performance critical. JC
  440. static void settings_to_globals()
  441. {
  442. LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
  443. BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
  444. BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
  445. MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
  446. MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
  447. LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
  448. LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile");
  449. LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
  450. LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor");
  451. LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f;
  452. LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
  453. LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
  454. LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor");
  455. LLVOAvatar::sPhysicsLODFactor = gSavedSettings.getF32("RenderAvatarPhysicsLODFactor");
  456. LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
  457. LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
  458. // clamp auto-open time to some minimum usable value
  459. LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
  460. LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
  461. LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
  462. LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
  463. gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns"));
  464. gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns"));
  465. gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
  466. gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
  467. gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
  468. LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
  469. }
  470. static void settings_modify()
  471. {
  472. LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred");
  473. LLPipeline::sRenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
  474. LLVOAvatar::sUseImpostors = gSavedSettings.getBOOL("RenderUseImpostors");
  475. LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
  476. LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
  477. gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
  478. gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
  479. gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
  480. }
  481. class LLFastTimerLogThread : public LLThread
  482. {
  483. public:
  484. std::string mFile;
  485. LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
  486. {
  487. std::string file_name = test_name + std::string(".slp");
  488. mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
  489. }
  490. void run()
  491. {
  492. std::ofstream os(mFile.c_str());
  493. while (!LLAppViewer::instance()->isQuitting())
  494. {
  495. LLFastTimer::writeLog(os);
  496. os.flush();
  497. ms_sleep(32);
  498. }
  499. os.close();
  500. }
  501. };
  502. //virtual
  503. bool LLAppViewer::initSLURLHandler()
  504. {
  505. // does nothing unless subclassed
  506. return false;
  507. }
  508. //virtual
  509. bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
  510. {
  511. // does nothing unless subclassed
  512. return false;
  513. }
  514. //----------------------------------------------------------------------------
  515. // LLAppViewer definition
  516. // Static members.
  517. // The single viewer app.
  518. LLAppViewer* LLAppViewer::sInstance = NULL;
  519. LLTextureCache* LLAppViewer::sTextureCache = NULL;
  520. LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL;
  521. LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
  522. LLAppViewer::LLAppViewer() :
  523. mMarkerFile(),
  524. mLogoutMarkerFile(NULL),
  525. mReportedCrash(false),
  526. mNumSessions(0),
  527. mPurgeCache(false),
  528. mPurgeOnExit(false),
  529. mSecondInstance(false),
  530. mSavedFinalSnapshot(false),
  531. mForceGraphicsDetail(false),
  532. mQuitRequested(false),
  533. mLogoutRequestSent(false),
  534. mYieldTime(-1),
  535. mMainloopTimeout(NULL),
  536. mAgentRegionLastAlive(false),
  537. mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
  538. mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
  539. mFastTimerLogThread(NULL),
  540. mUpdater(new LLUpdaterService()),
  541. mSettingsLocationList(NULL)
  542. {
  543. if(NULL != sInstance)
  544. {
  545. llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
  546. }
  547. setupErrorHandling();
  548. sInstance = this;
  549. gLoggedInTime.stop();
  550. LLLoginInstance::instance().setUpdaterService(mUpdater.get());
  551. }
  552. LLAppViewer::~LLAppViewer()
  553. {
  554. delete mSettingsLocationList;
  555. LLLoginInstance::instance().setUpdaterService(0);
  556. destroyMainloopTimeout();
  557. // If we got to this destructor somehow, the app didn't hang.
  558. removeMarkerFile();
  559. }
  560. bool LLAppViewer::init()
  561. {
  562. //
  563. // Start of the application
  564. //
  565. // IMPORTANT! Do NOT put anything that will write
  566. // into the log files during normal startup until AFTER
  567. // we run the "program crashed last time" error handler below.
  568. //
  569. LLFastTimer::reset();
  570. // initialize SSE options
  571. LLVector4a::initClass();
  572. // Need to do this initialization before we do anything else, since anything
  573. // that touches files should really go through the lldir API
  574. gDirUtilp->initAppDirs("SecondLife");
  575. // set skin search path to default, will be overridden later
  576. // this allows simple skinned file lookups to work
  577. gDirUtilp->setSkinFolder("default");
  578. initLogging();
  579. //
  580. // OK to write stuff to logs now, we've now crash reported if necessary
  581. //
  582. init_default_trans_args();
  583. if (!initConfiguration())
  584. return false;
  585. LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
  586. //set the max heap size.
  587. initMaxHeapSize() ;
  588. LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")) ;
  589. // write Google Breakpad minidump files to our log directory
  590. std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
  591. logdir += gDirUtilp->getDirDelimiter();
  592. setMiniDumpDir(logdir);
  593. // Although initLogging() is the right place to mess with
  594. // setFatalFunction(), we can't query gSavedSettings until after
  595. // initConfiguration().
  596. S32 rc(gSavedSettings.getS32("QAModeTermCode"));
  597. if (rc >= 0)
  598. {
  599. // QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit()
  600. // rather than exit() because normal cleanup depends too much on
  601. // successful startup!
  602. LLError::setFatalFunction(boost::bind(_exit, rc));
  603. }
  604. mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
  605. #if LL_RECORD_VIEWER_STATS
  606. LLViewerStatsRecorder::initClass();
  607. #endif
  608. // *NOTE:Mani - LLCurl::initClass is not thread safe.
  609. // Called before threads are created.
  610. LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"),
  611. gSavedSettings.getS32("CurlMaximumNumberOfHandles"),
  612. gSavedSettings.getBOOL("CurlUseMultipleThreads"));
  613. LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
  614. LLMachineID::init();
  615. {
  616. // Viewer metrics initialization
  617. static LLCachedControl<bool> metrics_submode(gSavedSettings,
  618. "QAModeMetrics",
  619. false,
  620. "Enables QA features (logging, faster cycling) for metrics collector");
  621. if (metrics_submode)
  622. {
  623. app_metrics_qa_mode = true;
  624. app_metrics_interval = METRICS_INTERVAL_QA;
  625. }
  626. LLViewerAssetStatsFF::init();
  627. }
  628. initThreads();
  629. LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;
  630. // Initialize settings early so that the defaults for ignorable dialogs are
  631. // picked up and then correctly re-saved after launching the updater (STORM-1268).
  632. LLUI::settings_map_t settings_map;
  633. settings_map["config"] = &gSavedSettings;
  634. settings_map["ignores"] = &gWarningSettings;
  635. settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
  636. settings_map["account"] = &gSavedPerAccountSettings;
  637. LLUI::initClass(settings_map,
  638. LLUIImageList::getInstance(),
  639. ui_audio_callback,
  640. &LLUI::sGLScaleFactor);
  641. LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
  642. // Setup paths and LLTrans after LLUI::initClass has been called.
  643. LLUI::setupPaths();
  644. LLTransUtil::parseStrings("strings.xml", default_trans_args);
  645. LLTransUtil::parseLanguageStrings("language_settings.xml");
  646. // Setup notifications after LLUI::setupPaths() has been called.
  647. LLNotifications::instance();
  648. LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
  649. writeSystemInfo();
  650. // Initialize updater service (now that we have an io pump)
  651. initUpdater();
  652. if(isQuitting())
  653. {
  654. // Early out here because updater set the quitting flag.
  655. return true;
  656. }
  657. //////////////////////////////////////////////////////////////////////////////
  658. //////////////////////////////////////////////////////////////////////////////
  659. //////////////////////////////////////////////////////////////////////////////
  660. //////////////////////////////////////////////////////////////////////////////
  661. // *FIX: The following code isn't grouped into functions yet.
  662. // Statistics / debug timer initialization
  663. init_statistics();
  664. //
  665. // Various introspection concerning the libs we're using - particularly
  666. // the libs involved in getting to a full login screen.
  667. //
  668. LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
  669. LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
  670. /////////////////////////////////////////////////
  671. // OS-specific login dialogs
  672. /////////////////////////////////////////////////
  673. //test_cached_control();
  674. // track number of times that app has run
  675. mNumSessions = gSavedSettings.getS32("NumSessions");
  676. mNumSessions++;
  677. gSavedSettings.setS32("NumSessions", mNumSessions);
  678. if (gSavedSettings.getBOOL("VerboseLogs"))
  679. {
  680. LLError::setPrintLocation(true);
  681. }
  682. // LLKeyboard relies on LLUI to know what some accelerator keys are called.
  683. LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
  684. LLWeb::initClass(); // do this after LLUI
  685. // Provide the text fields with callbacks for opening Urls
  686. LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
  687. LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
  688. LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
  689. LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
  690. // Let code in llui access the viewer help floater
  691. LLUI::sHelpImpl = LLViewerHelp::getInstance();
  692. LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ;
  693. // Load translations for tooltips
  694. LLFloater::initClass();
  695. /////////////////////////////////////////////////
  696. LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
  697. LLViewerFloaterReg::registerFloaters();
  698. /////////////////////////////////////////////////
  699. //
  700. // Load settings files
  701. //
  702. //
  703. LLGroupMgr::parseRoleActions("role_actions.xml");
  704. LLAgent::parseTeleportMessages("teleport_strings.xml");
  705. // load MIME type -> media impl mappings
  706. std::string mime_types_name;
  707. #if LL_DARWIN
  708. mime_types_name = "mime_types_mac.xml";
  709. #elif LL_LINUX
  710. mime_types_name = "mime_types_linux.xml";
  711. #else
  712. mime_types_name = "mime_types.xml";
  713. #endif
  714. LLMIMETypes::parseMIMETypes( mime_types_name );
  715. // Copy settings to globals. *TODO: Remove or move to appropriage class initializers
  716. settings_to_globals();
  717. // Setup settings listeners
  718. settings_setup_listeners();
  719. // Modify settings based on system configuration and compile options
  720. settings_modify();
  721. // Find partition serial number (Windows) or hardware serial (Mac)
  722. mSerialNumber = generateSerialNumber();
  723. // do any necessary set-up for accepting incoming SLURLs from apps
  724. initSLURLHandler();
  725. if(false == initHardwareTest())
  726. {
  727. // Early out from user choice.
  728. return false;
  729. }
  730. LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ;
  731. // Prepare for out-of-memory situations, during which we will crash on
  732. // purpose and save a dump.
  733. #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
  734. MemSetErrorHandler(first_mem_error_handler);
  735. #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
  736. // *Note: this is where gViewerStats used to be created.
  737. //
  738. // Initialize the VFS, and gracefully handle initialization errors
  739. //
  740. if (!initCache())
  741. {
  742. std::ostringstream msg;
  743. msg << LLTrans::getString("MBUnableToAccessFile");
  744. OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
  745. return 1;
  746. }
  747. LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
  748. // Initialize the repeater service.
  749. LLMainLoopRepeater::instance().start();
  750. //
  751. // Initialize the window
  752. //
  753. gGLActive = TRUE;
  754. initWindow();
  755. LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
  756. // initWindow also initializes the Feature List, so now we can initialize this global.
  757. LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
  758. // call all self-registered classes
  759. LLInitClassList::instance().fireCallbacks();
  760. LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
  761. gGLManager.getGLInfo(gDebugInfo);
  762. gGLManager.printGLInfoString();
  763. // Load Default bindings
  764. std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
  765. gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
  766. gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
  767. if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
  768. {
  769. std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
  770. gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
  771. gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
  772. if (!gViewerKeyboard.loadBindings(key_bindings_file))
  773. {
  774. LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
  775. }
  776. }
  777. // If we don't have the right GL requirements, exit.
  778. if (!gGLManager.mHasRequirements)
  779. {
  780. // can't use an alert here since we're exiting and
  781. // all hell breaks lose.
  782. OSMessageBox(
  783. LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
  784. LLStringUtil::null,
  785. OSMB_OK);
  786. return 0;
  787. }
  788. // Without SSE2 support we will crash almost immediately, warn here.
  789. if (!gSysCPU.hasSSE2())
  790. {
  791. // can't use an alert here since we're exiting and
  792. // all hell breaks lose.
  793. OSMessageBox(
  794. LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"),
  795. LLStringUtil::null,
  796. OSMB_OK);
  797. return 0;
  798. }
  799. // alert the user if they are using unsupported hardware
  800. if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
  801. {
  802. bool unsupported = false;
  803. LLSD args;
  804. std::string minSpecs;
  805. // get cpu data from xml
  806. std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
  807. S32 minCPU = 0;
  808. minCPUString >> minCPU;
  809. // get RAM data from XML
  810. std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
  811. U64 minRAM = 0;
  812. minRAMString >> minRAM;
  813. minRAM = minRAM * 1024 * 1024;
  814. if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
  815. {
  816. minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
  817. minSpecs += "\n";
  818. unsupported = true;
  819. }
  820. if(gSysCPU.getMHz() < minCPU)
  821. {
  822. minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
  823. minSpecs += "\n";
  824. unsupported = true;
  825. }
  826. if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
  827. {
  828. minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
  829. minSpecs += "\n";
  830. unsupported = true;
  831. }
  832. if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
  833. {
  834. LLNotificationsUtil::add("UnknownGPU");
  835. }
  836. if(unsupported)
  837. {
  838. if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
  839. || gSavedSettings.getBOOL("WarnUnsupportedHardware"))
  840. {
  841. args["MINSPECS"] = minSpecs;
  842. LLNotificationsUtil::add("UnsupportedHardware", args );
  843. }
  844. }
  845. }
  846. // save the graphics card
  847. gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
  848. // Save the current version to the prefs file
  849. gSavedSettings.setString("LastRunVersion",
  850. LLVersionInfo::getChannelAndVersion());
  851. gSimLastTime = gRenderStartTime.getElapsedTimeF32();
  852. gSimFrames = (F32)gFrameCount;
  853. LLViewerJoystick::getInstance()->init(false);
  854. try {
  855. initializeSecHandler();
  856. }
  857. catch (LLProtectedDataException ex)
  858. {
  859. LLNotificationsUtil::add("CorruptedProtectedDataStore");
  860. }
  861. LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
  862. gGLActive = FALSE;
  863. if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
  864. {
  865. loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
  866. }
  867. LLViewerMedia::initClass();
  868. LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ;
  869. LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
  870. //EXT-7013 - On windows for some locale (Japanese) standard
  871. //datetime formatting functions didn't support some parameters such as "weekday".
  872. //Names for days and months localized in xml are also useful for Polish locale(STORM-107).
  873. std::string language = gSavedSettings.getString("Language");
  874. if(language == "ja" || language == "pl")
  875. {
  876. LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
  877. LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
  878. LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
  879. LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
  880. LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
  881. LLStringOps::sAM = LLTrans::getString("dateTimeAM");
  882. LLStringOps::sPM = LLTrans::getString("dateTimePM");
  883. }
  884. LLAgentLanguage::init();
  885. return true;
  886. }
  887. void LLAppViewer::initMaxHeapSize()
  888. {
  889. //set the max heap size.
  890. //here is some info regarding to the max heap size:
  891. //------------------------------------------------------------------------------------------
  892. // OS | setting | SL address bits | max manageable memory space | max heap size
  893. // Win 32 | default | 32-bit | 2GB | < 1.7GB
  894. // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB
  895. //Linux 32 | default | 32-bit | 3GB | < 2.7GB
  896. //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB
  897. //64-bit OS |default | 32-bit | 4GB | < 3.7GB
  898. //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB)
  899. //------------------------------------------------------------------------------------------
  900. //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
  901. //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
  902. F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ;
  903. BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ;
  904. LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ;
  905. }
  906. void LLAppViewer::checkMemory()
  907. {
  908. const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
  909. //const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
  910. //static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
  911. if(!gGLManager.mDebugGPU)
  912. {
  913. return ;
  914. }
  915. if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
  916. {
  917. return ;
  918. }
  919. mMemCheckTimer.reset() ;
  920. //update the availability of memory
  921. LLMemory::updateMemoryInfo() ;
  922. bool is_low = LLMemory::isMemoryPoolLow() ;
  923. LLPipeline::throttleNewMemoryAllocation(is_low) ;
  924. if(is_low)
  925. {
  926. LLMemory::logMemoryInfo() ;
  927. }
  928. }
  929. static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
  930. static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep");
  931. static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");
  932. static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");
  933. static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread");
  934. static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread");
  935. static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
  936. static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
  937. static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
  938. static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares");
  939. static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service");
  940. static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback");
  941. static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot");
  942. static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update");
  943. bool LLAppViewer::mainLoop()
  944. {
  945. LLMemType mt1(LLMemType::MTYPE_MAIN);
  946. mMainloopTimeout = new LLWatchdogTimeout();
  947. //-------------------------------------------
  948. // Run main loop until time to quit
  949. //-------------------------------------------
  950. // Create IO Pump to use for HTTP Requests.
  951. gServicePump = new LLPumpIO(gAPRPoolp);
  952. LLHTTPClient::setPump(*gServicePump);
  953. LLCurl::setCAFile(gDirUtilp->getCAFile());
  954. // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
  955. LLVoiceChannel::initClass();
  956. LLVoiceClient::getInstance()->init(gServicePump);
  957. LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);
  958. LLTimer frameTimer,idleTimer;
  959. LLTimer debugTime;
  960. LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
  961. joystick->setNeedsReset(true);
  962. LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
  963. // As we do not (yet) send data on the mainloop LLEventPump that varies
  964. // with each frame, no need to instantiate a new LLSD event object each
  965. // time. Obviously, if that changes, just instantiate the LLSD at the
  966. // point of posting.
  967. LLSD newFrame;
  968. //LLPrivateMemoryPoolTester::getInstance()->run(false) ;
  969. //LLPrivateMemoryPoolTester::getInstance()->run(true) ;
  970. //LLPrivateMemoryPoolTester::destroy() ;
  971. // Handle messages
  972. while (!LLApp::isExiting())
  973. {
  974. LLFastTimer::nextFrame(); // Should be outside of any timer instances
  975. //clear call stack records
  976. llclearcallstacks;
  977. //check memory availability information
  978. checkMemory() ;
  979. try
  980. {
  981. pingMainloopTimeout("Main:MiscNativeWindowEvents");
  982. if (gViewerWindow)
  983. {
  984. LLFastTimer t2(FTM_MESSAGES);
  985. gViewerWindow->getWindow()->processMiscNativeEvents();
  986. }
  987. pingMainloopTimeout("Main:GatherInput");
  988. if (gViewerWindow)
  989. {
  990. LLFastTimer t2(FTM_MESSAGES);
  991. if (!restoreErrorTrap())
  992. {
  993. llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl;
  994. }
  995. gViewerWindow->getWindow()->gatherInput();
  996. }
  997. #if 1 && !LL_RELEASE_FOR_DOWNLOAD
  998. // once per second debug info
  999. if (debugTime.getElapsedTimeF32() > 1.f)
  1000. {
  1001. debugTime.reset();
  1002. }
  1003. #endif
  1004. //memory leaking simulation
  1005. LLFloaterMemLeak* mem_leak_instance =
  1006. LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
  1007. if(mem_leak_instance)
  1008. {
  1009. mem_leak_instance->idle() ;
  1010. }
  1011. // canonical per-frame event
  1012. mainloop.post(newFrame);
  1013. if (!LLApp::isExiting())
  1014. {
  1015. pingMainloopTimeout("Main:JoystickKeyboard");
  1016. // Scan keyboard for movement keys. Command keys and typing
  1017. // are handled by windows callbacks. Don't do this until we're
  1018. // done initializing. JC
  1019. if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
  1020. && gViewerWindow->getActive()
  1021. && !gViewerWindow->getWindow()->getMinimized()
  1022. && LLStartUp::getStartupState() == STATE_STARTED
  1023. && (gHeadlessClient || !gViewerWindow->getShowProgress())
  1024. && !gFocusMgr.focusLocked())
  1025. {
  1026. LLMemType mjk(LLMemType::MTYPE_JOY_KEY);
  1027. joystick->scanJoystick();
  1028. gKeyboard->scanKeyboard();
  1029. }
  1030. // Update state based on messages, user input, object idle.
  1031. {
  1032. pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
  1033. LLFastTimer t3(FTM_IDLE);
  1034. idle();
  1035. if (gAres != NULL && gAres->isInitialized())
  1036. {
  1037. LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP);
  1038. pingMainloopTimeout("Main:ServicePump");
  1039. LLFastTimer t4(FTM_PUMP);
  1040. {
  1041. LLFastTimer t(FTM_PUMP_ARES);
  1042. gAres->process();
  1043. }
  1044. {
  1045. LLFastTimer t(FTM_PUMP_SERVICE);
  1046. // this pump is necessary to make the login screen show up
  1047. gServicePump->pump();
  1048. {
  1049. LLFastTimer t(FTM_SERVICE_CALLBACK);
  1050. gServicePump->callback();
  1051. }
  1052. }
  1053. }
  1054. resumeMainloopTimeout();
  1055. }
  1056. if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
  1057. {
  1058. pauseMainloopTimeout();
  1059. saveFinalSnapshot();
  1060. disconnectViewer();
  1061. resumeMainloopTimeout();
  1062. }
  1063. // Render scene.
  1064. // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
  1065. if (!LLApp::isExiting() && !gHeadlessClient)
  1066. {
  1067. pingMainloopTimeout("Main:Display");
  1068. gGLActive = TRUE;
  1069. display();
  1070. pingMainloopTimeout("Main:Snapshot");
  1071. LLFloaterSnapshot::update(); // take snapshots
  1072. gGLActive = FALSE;
  1073. }
  1074. }
  1075. pingMainloopTimeout("Main:Sleep");
  1076. pauseMainloopTimeout();
  1077. // Sleep and run background threads
  1078. {
  1079. LLMemType mt_sleep(LLMemType::MTYPE_SLEEP);
  1080. LLFastTimer t2(FTM_SLEEP);
  1081. // yield some time to the os based on command line option
  1082. if(mYieldTime >= 0)
  1083. {
  1084. ms_sleep(mYieldTime);
  1085. }
  1086. // yield cooperatively when not running as foreground window
  1087. if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
  1088. || !gFocusMgr.getAppHasFocus())
  1089. {
  1090. // Sleep if we're not rendering, or the window is minimized.
  1091. S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
  1092. // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
  1093. // of equal priority on Windows
  1094. if (milliseconds_to_sleep > 0)
  1095. {
  1096. ms_sleep(milliseconds_to_sleep);
  1097. // also pause worker threads during this wait period
  1098. LLAppViewer::getTextureCache()->pause();
  1099. LLAppViewer::getImageDecodeThread()->pause();
  1100. }
  1101. }
  1102. if (mRandomizeFramerate)
  1103. {
  1104. ms_sleep(rand() % 200);
  1105. }
  1106. if (mPeriodicSlowFrame
  1107. && (gFrameCount % 10 == 0))
  1108. {
  1109. llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
  1110. ms_sleep(500);
  1111. }
  1112. static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds
  1113. const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second
  1114. idleTimer.reset();
  1115. bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
  1116. S32 total_work_pending = 0;
  1117. S32 total_io_pending = 0;
  1118. while(!is_slow)//do not unpause threads if the frame rates are very low.
  1119. {
  1120. S32 work_pending = 0;
  1121. S32 io_pending = 0;
  1122. F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
  1123. {
  1124. LLFastTimer ftm(FTM_TEXTURE_CACHE);
  1125. work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
  1126. }
  1127. {
  1128. LLFastTimer ftm(FTM_DECODE);
  1129. work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
  1130. }
  1131. {
  1132. LLFastTimer ftm(FTM_DECODE);
  1133. work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
  1134. }
  1135. {
  1136. LLFastTimer ftm(FTM_VFS);
  1137. io_pending += LLVFSThread::updateClass(1);
  1138. }
  1139. {
  1140. LLFastTimer ftm(FTM_LFS);
  1141. io_pending += LLLFSThread::updateClass(1);
  1142. }
  1143. if (io_pending > 1000)
  1144. {
  1145. ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
  1146. }
  1147. total_work_pending += work_pending ;
  1148. total_io_pending += io_pending ;
  1149. if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
  1150. {
  1151. break;
  1152. }
  1153. }
  1154. gMeshRepo.update() ;
  1155. if(!LLCurl::getCurlThread()->update(1))
  1156. {
  1157. LLCurl::getCurlThread()->pause() ; //nothing in the curl thread.
  1158. }
  1159. if(!total_work_pending) //pause texture fetching threads if nothing to process.
  1160. {
  1161. LLAppViewer::getTextureCache()->pause();
  1162. LLAppViewer::getImageDecodeThread()->pause();
  1163. LLAppViewer::getTextureFetch()->pause();
  1164. }
  1165. if(!total_io_pending) //pause file threads if nothing to process.
  1166. {
  1167. LLVFSThread::sLocal->pause();
  1168. LLLFSThread::sLocal->pause();
  1169. }
  1170. if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
  1171. (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
  1172. {
  1173. gFrameStalls++;
  1174. }
  1175. frameTimer.reset();
  1176. resumeMainloopTimeout();
  1177. pingMainloopTimeout("Main:End");
  1178. }
  1179. }
  1180. catch(std::bad_alloc)
  1181. {
  1182. LLMemory::logMemoryInfo(TRUE) ;
  1183. //stop memory leaking simulation
  1184. LLFloaterMemLeak* mem_leak_instance =
  1185. LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
  1186. if(mem_leak_instance)
  1187. {
  1188. mem_leak_instance->stop() ;
  1189. llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
  1190. }
  1191. else
  1192. {
  1193. //output possible call stacks to log file.
  1194. LLError::LLCallStacks::print() ;
  1195. llerrs << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
  1196. }
  1197. }
  1198. }
  1199. // Save snapshot for next time, if we made it through initialization
  1200. if (STATE_STARTED == LLStartUp::getStartupState())
  1201. {
  1202. try
  1203. {
  1204. saveFinalSnapshot();
  1205. }
  1206. catch(std::bad_alloc)
  1207. {
  1208. llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
  1209. //stop memory leaking simulation
  1210. LLFloaterMemLeak* mem_leak_instance =
  1211. LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
  1212. if(mem_leak_instance)
  1213. {
  1214. mem_leak_instance->stop() ;
  1215. }
  1216. }
  1217. }
  1218. delete gServicePump;
  1219. destroyMainloopTimeout();
  1220. llinfos << "Exiting main_loop" << llendflush;
  1221. return true;
  1222. }
  1223. void LLAppViewer::flushVFSIO()
  1224. {
  1225. while (1)
  1226. {
  1227. S32 pending = LLVFSThread::updateClass(0);
  1228. pending += LLLFSThread::updateClass(0);
  1229. if (!pending)
  1230. {
  1231. break;
  1232. }
  1233. llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
  1234. ms_sleep(100);
  1235. }
  1236. }
  1237. bool LLAppViewer::cleanup()
  1238. {
  1239. // workaround for DEV-35406 crash on shutdown
  1240. LLEventPumps::instance().reset();
  1241. if (LLFastTimerView::sAnalyzePerformance)
  1242. {
  1243. llinfos << "Analyzing performance" << llendl;
  1244. std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
  1245. std::string current_name = LLFastTimer::sLogName + ".slp";
  1246. std::string report_name = LLFastTimer::sLogName + "_report.csv";
  1247. LLFastTimerView::doAnalysis(
  1248. gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
  1249. gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
  1250. gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
  1251. }
  1252. LLMetricPerformanceTesterBasic::cleanClass();
  1253. // remove any old breakpad minidump files from the log directory
  1254. if (! isError())
  1255. {
  1256. std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
  1257. logdir += gDirUtilp->getDirDelimiter();
  1258. gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
  1259. }
  1260. // *TODO - generalize this and move DSO wrangling to a helper class -brad
  1261. std::set<struct apr_dso_handle_t *>::const_iterator i;
  1262. for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
  1263. {
  1264. int (*ll_plugin_stop_func)(void) = NULL;
  1265. apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
  1266. ll_plugin_stop_func();
  1267. rv = apr_dso_unload(*i);
  1268. }
  1269. mPlugins.clear();
  1270. //flag all elements as needing to be destroyed immediately
  1271. // to ensure shutdown order
  1272. LLMortician::setZealous(TRUE);
  1273. LLVoiceClient::getInstance()->terminate();
  1274. disconnectViewer();
  1275. llinfos << "Viewer disconnected" << llendflush;
  1276. display_cleanup();
  1277. release_start_screen(); // just in case
  1278. LLError::logToFixedBuffer(NULL);
  1279. llinfos << "Cleaning Up" << llendflush;
  1280. // shut down mesh streamer
  1281. gMeshRepo.shutdown();
  1282. // Must clean up texture references before viewer window is destroyed.
  1283. if(LLHUDManager::instanceExists())
  1284. {
  1285. LLHUDManager::getInstance()->updateEffects();
  1286. LLHUDObject::updateAll();
  1287. LLHUDManager::getInstance()->cleanupEffects();
  1288. LLHUDObject::cleanupHUDObjects();
  1289. llinfos << "HUD Objects cleaned up" << llendflush;
  1290. }
  1291. LLKeyframeDataCache::clear();
  1292. // End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
  1293. #if 0 // this seems to get us stuck in an infinite loop...
  1294. gTransferManager.cleanup();
  1295. #endif
  1296. // Note: this is where gWorldMap used to be deleted.
  1297. // Note: this is where gHUDManager used to be deleted.
  1298. if(LLHUDManager::instanceExists())
  1299. {
  1300. LLHUDManager::getInstance()->shutdownClass();
  1301. }
  1302. delete gAssetStorage;
  1303. gAssetStorage = NULL;
  1304. LLPolyMesh::freeAllMeshes();
  1305. LLStartUp::cleanupNameCache();
  1306. // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
  1307. LLWorldMap::getInstance()->reset(); // release any images
  1308. LLCalc::cleanUp();
  1309. llinfos << "Global stuff deleted" << llendflush;
  1310. if (gAudiop)
  1311. {
  1312. // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
  1313. LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
  1314. delete sai;
  1315. gAudiop->setStreamingAudioImpl(NULL);
  1316. // shut down the audio subsystem
  1317. bool want_longname = false;
  1318. if (gAudiop->getDriverName(want_longname) == "FMOD")
  1319. {
  1320. // This hack exists because fmod likes to occasionally
  1321. // crash or hang forever when shutting down, for no
  1322. // apparent reason.
  1323. llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
  1324. }
  1325. else
  1326. {
  1327. gAudiop->shutdown();
  1328. }
  1329. delete gAudiop;
  1330. gAudiop = NULL;
  1331. }
  1332. // Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
  1333. // Patch up settings for next time
  1334. // Must do this before we delete the viewer window,
  1335. // such that we can suck rectangle information out of
  1336. // it.
  1337. cleanupSavedSettings();
  1338. llinfos << "Settings patched up" << llendflush;
  1339. // delete some of the files left around in the cache.
  1340. removeCacheFiles("*.wav");
  1341. removeCacheFiles("*.tmp");
  1342. removeCacheFiles("*.lso");
  1343. removeCacheFiles("*.out");
  1344. removeCacheFiles("*.dsf");
  1345. removeCacheFiles("*.bodypart");
  1346. removeCacheFiles("*.clothing");
  1347. llinfos << "Cache files removed" << llendflush;
  1348. // Wait for any pending VFS IO
  1349. flushVFSIO();
  1350. llinfos << "Shutting down Views" << llendflush;
  1351. // Destroy the UI
  1352. if( gViewerWindow)
  1353. gViewerWindow->shutdownViews();
  1354. llinfos << "Cleaning up Inventory" << llendflush;
  1355. // Cleanup Inventory after the UI since it will delete any remaining observers
  1356. // (Deleted observers should have already removed themselves)
  1357. gInventory.cleanupInventory();
  1358. llinfos << "Cleaning up Selections" << llendflush;
  1359. // Clean up selection managers after UI is destroyed, as UI may be observing them.
  1360. // Clean up before GL is shut down because we might be holding on to objects with texture references
  1361. LLSelectMgr::cleanupGlobals();
  1362. llinfos << "Shutting down OpenGL" << llendflush;
  1363. // Shut down OpenGL
  1364. if( gViewerWindow)
  1365. {
  1366. gViewerWindow->shutdownGL();
  1367. // Destroy window, and make sure we're not fullscreen
  1368. // This may generate window reshape and activation events.
  1369. // Therefore must do this before destroying the message system.
  1370. delete gViewerWindow;
  1371. gViewerWindow = NULL;
  1372. llinfos << "ViewerWindow deleted" << llendflush;
  1373. }
  1374. llinfos << "Cleaning up Keyboard & Joystick" << llendflush;
  1375. // viewer UI relies on keyboard so keep it aound until viewer UI isa gone
  1376. delete gKeyboard;
  1377. gKeyboard = NULL;
  1378. // Turn off Space Navigator and similar devices
  1379. LLViewerJoystick::getInstance()->terminate();
  1380. llinfos << "Cleaning up Objects" << llendflush;
  1381. LLViewerObject::cleanupVOClasses();
  1382. LLPostProcess::cleanupClass();
  1383. LLTracker::cleanupInstance();
  1384. // *FIX: This is handled in LLAppViewerWin32::cleanup().
  1385. // I'm keeping the comment to remember its order in cleanup,
  1386. // in case of unforseen dependency.
  1387. //#if LL_WINDOWS
  1388. // gDXHardware.cleanup();
  1389. //#endif // LL_WINDOWS
  1390. LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
  1391. if (!volume_manager->cleanup())
  1392. {
  1393. llwarns << "Remaining references in the volume manager!" << llendflush;
  1394. }
  1395. LLPrimitive::cleanupVolumeManager();
  1396. llinfos << "Additional Cleanup..." << llendflush;
  1397. LLViewerParcelMgr::cleanupGlobals();
  1398. // *Note: this is where gViewerStats used to be deleted.
  1399. //end_messaging_system();
  1400. LLFollowCamMgr::cleanupClass();
  1401. //LLVolumeMgr::cleanupClass();
  1402. LLPrimitive::cleanupVolumeManager();
  1403. LLWorldMapView::cleanupClass();
  1404. LLFolderViewItem::cleanupClass();
  1405. LLUI::cleanupClass();
  1406. //
  1407. // Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
  1408. // Also after viewerwindow is deleted, since it may have image pointers (which have vfiles)
  1409. // Also after shutting down the messaging system since it has VFS dependencies
  1410. //
  1411. llinfos << "Cleaning up VFS" << llendflush;
  1412. LLVFile::cleanupClass();
  1413. llinfos << "Saving Data" << llendflush;
  1414. // Store the time of our current logoff
  1415. gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
  1416. // Must do this after all panels have been deleted because panels that have persistent rects
  1417. // save their rects on delete.
  1418. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
  1419. LLUIColorTable::instance().saveUserSettings();
  1420. // PerAccountSettingsFile should be empty if no user has been logged on.
  1421. // *FIX:Mani This should get really saved in a "logoff" mode.
  1422. if (gSavedSettings.getString("PerAccountSettingsFile").empty())
  1423. {
  1424. llinfos << "Not saving per-account settings; don't know the account name yet." << llendl;
  1425. }
  1426. else
  1427. {
  1428. gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
  1429. llinfos << "Saved settings" << llendflush;
  1430. }
  1431. std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
  1432. gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
  1433. // Save URL history file
  1434. LLURLHistory::saveFile("url_history.xml");
  1435. // save mute list. gMuteList used to also be deleted here too.
  1436. LLMuteList::getInstance()->cache(gAgent.getID());
  1437. if (mPurgeOnExit)
  1438. {
  1439. llinfos << "Purging all cache files on exit" << llendflush;
  1440. std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
  1441. gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
  1442. }
  1443. removeMarkerFile(); // Any crashes from here on we'll just have to ignore
  1444. writeDebugInfo();
  1445. LLLocationHistory::getInstance()->save();
  1446. LLAvatarIconIDCache::getInstance()->save();
  1447. LLViewerMedia::saveCookieFile();
  1448. // Stop the plugin read thread if it's running.
  1449. LLPluginProcessParent::setUseReadThread(false);
  1450. llinfos << "Shutting down Threads" << llendflush;
  1451. // Let threads finish
  1452. LLTimer idleTimer;
  1453. idleTimer.reset();
  1454. const F64 max_idle_time = 5.f; // 5 seconds
  1455. while(1)
  1456. {
  1457. S32 pending = 0;
  1458. pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
  1459. pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
  1460. pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
  1461. pending += LLVFSThread::updateClass(0);
  1462. pending += LLLFSThread::updateClass(0);
  1463. pending += LLCurl::getCurlThread()->update(1) ;
  1464. F64 idle_time = idleTimer.getElapsedTimeF64();
  1465. if(!pending)
  1466. {
  1467. break ; //done
  1468. }
  1469. else if(idle_time >= max_idle_time)
  1470. {
  1471. llwarns << "Quitting with pending background tasks." << llendl;
  1472. break;
  1473. }
  1474. }
  1475. LLCurl::getCurlThread()->pause() ;
  1476. // Delete workers first
  1477. // shotdown all worker threads before deleting them in case of co-dependencies
  1478. sTextureFetch->shutdown();
  1479. sTextureCache->shutdown();
  1480. sImageDecodeThread->shutdown();
  1481. sTextureFetch->shutDownTextureCacheThread() ;
  1482. sTextureFetch->shutDownImageDecodeThread() ;
  1483. LLFilePickerThread::cleanupClass();
  1484. delete sTextureCache;
  1485. sTextureCache = NULL;
  1486. delete sTextureFetch;
  1487. sTextureFetch = NULL;
  1488. delete sImageDecodeThread;
  1489. sImageDecodeThread = NULL;
  1490. delete mFastTimerLogThread;
  1491. mFastTimerLogThread = NULL;
  1492. if (LLFastTimerView::sAnalyzePerformance)
  1493. {
  1494. llinfos << "Analyzing performance" << llendl;
  1495. std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
  1496. std::string current_name = LLFastTimer::sLogName + ".slp";
  1497. std::string report_name = LLFastTimer::sLogName + "_report.csv";
  1498. LLFastTimerView::doAnalysis(
  1499. gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
  1500. gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
  1501. gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
  1502. }
  1503. LLMetricPerformanceTesterBasic::cleanClass() ;
  1504. #if LL_RECORD_VIEWER_STATS
  1505. LLViewerStatsRecorder::cleanupClass();
  1506. #endif
  1507. llinfos << "Cleaning up Media and Textures" << llendflush;
  1508. //Note:
  1509. //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
  1510. //because some new image might be generated during cleaning up media. --bao
  1511. LLViewerMedia::cleanupClass();
  1512. LLViewerParcelMedia::cleanupClass();
  1513. gTextureList.shutdown(); // shutdown again in case a callback added something
  1514. LLUIImageList::getInstance()->cleanUp();
  1515. // This should eventually be done in LLAppViewer
  1516. LLImage::cleanupClass();
  1517. LLVFSThread::cleanupClass();
  1518. LLLFSThread::cleanupClass();
  1519. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1520. llinfos << "Auditing VFS" << llendl;
  1521. if(gVFS)
  1522. {
  1523. gVFS->audit();
  1524. }
  1525. #endif
  1526. llinfos << "Misc Cleanup" << llendflush;
  1527. // For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
  1528. // (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
  1529. delete gStaticVFS;
  1530. gStaticVFS = NULL;
  1531. delete gVFS;
  1532. gVFS = NULL;
  1533. gSavedSettings.cleanup();
  1534. LLUIColorTable::instance().clear();
  1535. LLWatchdog::getInstance()->cleanup();
  1536. LLViewerAssetStatsFF::cleanup();
  1537. llinfos << "Shutting down message system" << llendflush;
  1538. end_messaging_system();
  1539. // *NOTE:Mani - The following call is not thread safe.
  1540. LLCurl::cleanupClass();
  1541. // If we're exiting to launch an URL, do that here so the screen
  1542. // is at the right resolution before we launch IE.
  1543. if (!gLaunchFileOnQuit.empty())
  1544. {
  1545. llinfos << "Launch file on quit." << llendflush;
  1546. #if LL_WINDOWS
  1547. // Indicate an application is starting.
  1548. SetCursor(LoadCursor(NULL, IDC_WAIT));
  1549. #endif
  1550. // HACK: Attempt to wait until the screen res. switch is complete.
  1551. ms_sleep(1000);
  1552. LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
  1553. llinfos << "File launched." << llendflush;
  1554. }
  1555. llinfos << "Cleaning up LLProxy." << llendl;
  1556. LLProxy::cleanupClass();
  1557. LLMainLoopRepeater::instance().stop();
  1558. //release all private memory pools.
  1559. LLPrivateMemoryPoolManager::destroyClass() ;
  1560. ll_close_fail_log();
  1561. MEM_TRACK_RELEASE
  1562. llinfos << "Goodbye!" << llendflush;
  1563. // return 0;
  1564. return true;
  1565. }
  1566. // A callback for llerrs to call during the watchdog error.
  1567. void watchdog_llerrs_callback(const std::string &error_string)
  1568. {
  1569. gLLErrorActivated = true;
  1570. #ifdef LL_WINDOWS
  1571. RaiseException(0,0,0,0);
  1572. #else
  1573. raise(SIGQUIT);
  1574. #endif
  1575. }
  1576. // A callback for the watchdog to call.
  1577. void watchdog_killer_callback()
  1578. {
  1579. LLError::setFatalFunction(watchdog_llerrs_callback);
  1580. llerrs << "Watchdog killer event" << llendl;
  1581. }
  1582. bool LLAppViewer::initThreads()
  1583. {
  1584. #if MEM_TRACK_MEM
  1585. static const bool enable_threads = false;
  1586. #else
  1587. static const bool enable_threads = true;
  1588. #endif
  1589. LLImage::initClass();
  1590. LLVFSThread::initClass(enable_threads && false);
  1591. LLLFSThread::initClass(enable_threads && false);
  1592. // Image decoding
  1593. LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
  1594. LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
  1595. LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
  1596. sImageDecodeThread,
  1597. enable_threads && true,
  1598. app_metrics_qa_mode);
  1599. if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
  1600. {
  1601. LLFastTimer::sLogLock = new LLMutex(NULL);
  1602. mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
  1603. mFastTimerLogThread->start();
  1604. }
  1605. // Mesh streaming and caching
  1606. gMeshRepo.init();
  1607. LLFilePickerThread::initClass();
  1608. // *FIX: no error handling here!
  1609. return true;
  1610. }
  1611. void errorCallback(const std::string &error_string)
  1612. {
  1613. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1614. OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
  1615. #endif
  1616. //Set the ErrorActivated global so we know to create a marker file
  1617. gLLErrorActivated = true;
  1618. LLError::crashAndLoop(error_string);
  1619. }
  1620. bool LLAppViewer::initLogging()
  1621. {
  1622. //
  1623. // Set up logging defaults for the viewer
  1624. //
  1625. LLError::initForApplication(
  1626. gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
  1627. LLError::setFatalFunction(errorCallback);
  1628. // Remove the last ".old" log file.
  1629. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
  1630. "SecondLife.old");
  1631. LLFile::remove(old_log_file);
  1632. // Rename current log file to ".old"
  1633. std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
  1634. "SecondLife.log");
  1635. LLFile::rename(log_file, old_log_file);
  1636. // Set the log file to SecondLife.log
  1637. LLError::logToFile(log_file);
  1638. // *FIX:Mani no error handling here!
  1639. return true;
  1640. }
  1641. bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
  1642. bool set_defaults)
  1643. {
  1644. if (!mSettingsLocationList)
  1645. {
  1646. llerrs << "Invalid settings location list" << llendl;
  1647. }
  1648. BOOST_FOREACH(const SettingsGroup& group, mSettingsLocationList->groups)
  1649. {
  1650. // skip settings groups that aren't the one we requested
  1651. if (group.name() != location_key) continue;
  1652. ELLPath path_index = (ELLPath)group.path_index();
  1653. if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
  1654. {
  1655. llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
  1656. return false;
  1657. }
  1658. BOOST_FOREACH(const SettingsFile& file, group.files)
  1659. {
  1660. llinfos << "Attempting to load settings for the group " << file.name()
  1661. << " - from location " << location_key << llendl;
  1662. LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);
  1663. if(!settings_group)
  1664. {
  1665. llwarns << "No matching settings group for name " << file.name() << llendl;
  1666. continue;
  1667. }
  1668. std::string full_settings_path;
  1669. if (file.file_name_setting.isProvided()
  1670. && gSavedSettings.controlExists(file.file_name_setting))
  1671. {
  1672. // try to find filename stored in file_name_setting control
  1673. full_settings_path = gSavedSettings.getString(file.file_name_setting);
  1674. if (full_settings_path.empty())
  1675. {
  1676. continue;
  1677. }
  1678. else if (!gDirUtilp->fileExists(full_settings_path))
  1679. {
  1680. // search in default path
  1681. full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
  1682. }
  1683. }
  1684. else
  1685. {
  1686. // by default, use specified file name
  1687. full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name());
  1688. }
  1689. if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
  1690. { // success!
  1691. llinfos << "Loaded settings file " << full_settings_path << llendl;
  1692. }
  1693. else
  1694. { // failed to load
  1695. if(file.required)
  1696. {
  1697. llerrs << "Error: Cannot load required settings file from: " << full_settings_path << llendl;
  1698. return false;
  1699. }
  1700. else
  1701. {
  1702. // only complain if we actually have a filename at this point
  1703. if (!full_settings_path.empty())
  1704. {
  1705. llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
  1706. }
  1707. }
  1708. }
  1709. }
  1710. }
  1711. return true;
  1712. }
  1713. std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
  1714. const std::string& file)
  1715. {
  1716. BOOST_FOREACH(const SettingsGroup& group, mSettingsLocationList->groups)
  1717. {
  1718. if (group.name() == location_key)
  1719. {
  1720. BOOST_FOREACH(const SettingsFile& settings_file, group.files)
  1721. {
  1722. if (settings_file.name() == file)
  1723. {
  1724. return settings_file.file_name;
  1725. }
  1726. }
  1727. }
  1728. }
  1729. return std::string();
  1730. }
  1731. void LLAppViewer::loadColorSettings()
  1732. {
  1733. LLUIColorTable::instance().loadFromSettings();
  1734. }
  1735. bool LLAppViewer::initConfiguration()
  1736. {
  1737. //Load settings files list
  1738. std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
  1739. //LLControlGroup settings_control("SettingsFiles");
  1740. //llinfos << "Loading settings file list " << settings_file_list << llendl;
  1741. //if (0 == settings_control.loadFromFile(settings_file_list))
  1742. //{
  1743. // llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
  1744. //}
  1745. LLXMLNodePtr root;
  1746. BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
  1747. if (!success)
  1748. {
  1749. llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
  1750. }
  1751. mSettingsLocationList = new SettingsFiles();
  1752. LLXUIParser parser;
  1753. parser.readXUI(root, *mSettingsLocationList, settings_file_list);
  1754. if (!mSettingsLocationList->validateBlock())
  1755. {
  1756. llerrs << "Invalid settings file list " << settings_file_list << llendl;
  1757. }
  1758. // The settings and command line parsing have a fragile
  1759. // order-of-operation:
  1760. // - load defaults from app_settings
  1761. // - set procedural settings values
  1762. // - read command line settings
  1763. // - selectively apply settings needed to load user settings.
  1764. // - load overrides from user_settings
  1765. // - apply command line settings (to override the overrides)
  1766. // - load per account settings (happens in llstartup
  1767. // - load defaults
  1768. bool set_defaults = true;
  1769. if(!loadSettingsFromDirectory("Default", set_defaults))
  1770. {
  1771. std::ostringstream msg;
  1772. msg << "Unable to load default settings file. The installation may be corrupted.";
  1773. OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
  1774. return false;
  1775. }
  1776. LLUI::setupPaths(); // setup paths for LLTrans based on settings files only
  1777. LLTransUtil::parseStrings("strings.xml", default_trans_args);
  1778. LLTransUtil::parseLanguageStrings("language_settings.xml");
  1779. // - set procedural settings
  1780. // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
  1781. gSavedSettings.setString("ClientSettingsFile",
  1782. gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
  1783. gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel());
  1784. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1785. // provide developer build only overrides for these control variables that are not
  1786. // persisted to settings.xml
  1787. LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow");
  1788. if (c)
  1789. {
  1790. c->setValue(true, false);
  1791. }
  1792. c = gSavedSettings.getCont