aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llappviewer.cpp')
-rw-r--r--linden/indra/newview/llappviewer.cpp299
1 files changed, 155 insertions, 144 deletions
diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp
index b2bfccf..4d53c88 100644
--- a/linden/indra/newview/llappviewer.cpp
+++ b/linden/indra/newview/llappviewer.cpp
@@ -4,7 +4,7 @@
4 * 4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$ 5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 * 6 *
7 * Copyright (c) 2007-2008, Linden Research, Inc. 7 * Copyright (c) 2007-2009, Linden Research, Inc.
8 * 8 *
9 * Second Life Viewer Source Code 9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab 10 * The source code in this file ("Source Code") is provided by Linden Lab
@@ -192,35 +192,22 @@
192 192
193//---------------------------------------------------------------------------- 193//----------------------------------------------------------------------------
194// viewer.cpp - these are only used in viewer, should be easily moved. 194// viewer.cpp - these are only used in viewer, should be easily moved.
195extern void disable_win_error_reporting();
196 195
197#if LL_DARWIN 196#if LL_DARWIN
198#include <Carbon/Carbon.h>
199extern void init_apple_menu(const char* product); 197extern void init_apple_menu(const char* product);
200extern OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
201extern OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
202extern OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata);
203#include <boost/tokenizer.hpp>
204#endif // LL_DARWIN 198#endif // LL_DARWIN
205 199
206
207extern BOOL gRandomizeFramerate; 200extern BOOL gRandomizeFramerate;
208extern BOOL gPeriodicSlowFrame; 201extern BOOL gPeriodicSlowFrame;
209extern BOOL gDebugGL; 202extern BOOL gDebugGL;
210 203
211//////////////////////////////////////////////////////////// 204////////////////////////////////////////////////////////////
212// All from the last globals push... 205// All from the last globals push...
213BOOL gHandleKeysAsync = FALSE;
214
215const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user flagged as Away From Keyboard 206const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user flagged as Away From Keyboard
216 207
217F32 gSimLastTime; // Used in LLAppViewer::init and send_stats() 208F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
218F32 gSimFrames; 209F32 gSimFrames;
219 210
220std::string gDisabledMessage; // Set in LLAppViewer::initConfiguration used in idle_startup
221
222BOOL gHideLinks = FALSE; // Set in LLAppViewer::initConfiguration, used externally
223
224BOOL gAllowIdleAFK = TRUE; 211BOOL gAllowIdleAFK = TRUE;
225BOOL gAllowTapTapHoldRun = TRUE; 212BOOL gAllowTapTapHoldRun = TRUE;
226BOOL gShowObjectUpdates = FALSE; 213BOOL gShowObjectUpdates = FALSE;
@@ -246,7 +233,7 @@ F32 gFPSClamped = 10.f; // Pretend we start at target rate.
246F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets 233F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets
247U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds 234U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
248U32 gFrameStalls = 0; 235U32 gFrameStalls = 0;
249const F64 FRAME_STALL_THRESHOLD = 5.0; 236const F64 FRAME_STALL_THRESHOLD = 1.0;
250 237
251LLTimer gRenderStartTime; 238LLTimer gRenderStartTime;
252LLFrameTimer gForegroundTime; 239LLFrameTimer gForegroundTime;
@@ -261,7 +248,6 @@ BOOL gDisconnected = FALSE;
261 248
262// Map scale in pixels per region 249// Map scale in pixels per region
263F32 gMapScale = 128.f; 250F32 gMapScale = 128.f;
264F32 gMiniMapScale = 128.f;
265 251
266// used to restore texture state after a mode switch 252// used to restore texture state after a mode switch
267LLFrameTimer gRestoreGLTimer; 253LLFrameTimer gRestoreGLTimer;
@@ -316,6 +302,7 @@ std::string gLoginPage;
316std::vector<std::string> gLoginURIs; 302std::vector<std::string> gLoginURIs;
317static std::string gHelperURI; 303static std::string gHelperURI;
318 304
305LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
319 306
320void idle_afk_check() 307void idle_afk_check()
321{ 308{
@@ -331,8 +318,7 @@ static void ui_audio_callback(const LLUUID& uuid)
331{ 318{
332 if (gAudiop) 319 if (gAudiop)
333 { 320 {
334 F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"); 321 gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
335 gAudiop->triggerSound(uuid, gAgent.getID(), volume);
336 } 322 }
337} 323}
338 324
@@ -405,6 +391,7 @@ static void settings_to_globals()
405 LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay")); 391 LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
406 LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay"); 392 LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay");
407 LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive"); 393 LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
394 LLSelectMgr::sRenderSelectionHighlights = gSavedSettings.getBOOL("RenderHighlightSelections");
408 LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections"); 395 LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
409 LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); 396 LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
410 397
@@ -418,8 +405,6 @@ static void settings_to_globals()
418 gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun"); 405 gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
419 gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); 406 gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
420 gMapScale = gSavedSettings.getF32("MapScale"); 407 gMapScale = gSavedSettings.getF32("MapScale");
421 gMiniMapScale = gSavedSettings.getF32("MiniMapScale");
422 gHandleKeysAsync = gSavedSettings.getBOOL("AsyncKeyboard");
423 LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips"); 408 LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
424 409
425 LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); 410 LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
@@ -498,30 +483,17 @@ void LLAppViewer::initGridChoice()
498 } 483 }
499} 484}
500 485
501bool send_url_to_other_instance(const std::string& url) 486//virtual
487bool LLAppViewer::initSLURLHandler()
502{ 488{
503#if LL_WINDOWS 489 // does nothing unless subclassed
504 wchar_t window_class[256]; /* Flawfinder: ignore */ // Assume max length < 255 chars. 490 return false;
505 mbstowcs(window_class, sWindowClass, 255); 491}
506 window_class[255] = 0; 492
507 // Use the class instead of the window name. 493//virtual
508 HWND other_window = FindWindow(window_class, NULL); 494bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
509 495{
510 if (other_window != NULL) 496 // does nothing unless subclassed
511 {
512 lldebugs << "Found other window with the name '" << gWindowTitle << "'" << llendl;
513 COPYDATASTRUCT cds;
514 const S32 SLURL_MESSAGE_TYPE = 0;
515 cds.dwData = SLURL_MESSAGE_TYPE;
516 cds.cbData = url.length() + 1;
517 cds.lpData = (void*)url.c_str();
518
519 LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&cds);
520 lldebugs << "SendMessage(WM_COPYDATA) to other window '"
521 << gWindowTitle << "' returned " << msg_result << llendl;
522 return true;
523 }
524#endif
525 return false; 497 return false;
526} 498}
527 499
@@ -690,6 +662,7 @@ bool LLAppViewer::init()
690 ui_audio_callback, 662 ui_audio_callback,
691 &LLUI::sGLScaleFactor); 663 &LLUI::sGLScaleFactor);
692 LLWeb::initClass(); // do this after LLUI 664 LLWeb::initClass(); // do this after LLUI
665
693 LLTextEditor::setURLCallbacks(&LLWeb::loadURL, 666 LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
694 &LLURLDispatcher::dispatchFromTextEditor, 667 &LLURLDispatcher::dispatchFromTextEditor,
695 &LLURLDispatcher::dispatchFromTextEditor); 668 &LLURLDispatcher::dispatchFromTextEditor);
@@ -710,7 +683,6 @@ bool LLAppViewer::init()
710 // load MIME type -> media impl mappings 683 // load MIME type -> media impl mappings
711 LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") ); 684 LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") );
712 685
713
714 // Copy settings to globals. *TODO: Remove or move to appropriage class initializers 686 // Copy settings to globals. *TODO: Remove or move to appropriage class initializers
715 settings_to_globals(); 687 settings_to_globals();
716 // Setup settings listeners 688 // Setup settings listeners
@@ -721,6 +693,9 @@ bool LLAppViewer::init()
721 // Find partition serial number (Windows) or hardware serial (Mac) 693 // Find partition serial number (Windows) or hardware serial (Mac)
722 mSerialNumber = generateSerialNumber(); 694 mSerialNumber = generateSerialNumber();
723 695
696 // do any necessary set-up for accepting incoming SLURLs from apps
697 initSLURLHandler();
698
724 if(false == initHardwareTest()) 699 if(false == initHardwareTest())
725 { 700 {
726 // Early out from user choice. 701 // Early out from user choice.
@@ -851,7 +826,10 @@ bool LLAppViewer::init()
851 } 826 }
852 827
853 } 828 }
854 829
830 // save the graphics card
831 gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
832
855 // Save the current version to the prefs file 833 // Save the current version to the prefs file
856 gSavedSettings.setString("LastRunVersion", gCurrentVersion); 834 gSavedSettings.setString("LastRunVersion", gCurrentVersion);
857 835
@@ -896,16 +874,21 @@ bool LLAppViewer::mainLoop()
896 { 874 {
897 LLFastTimer t(LLFastTimer::FTM_FRAME); 875 LLFastTimer t(LLFastTimer::FTM_FRAME);
898 876
877 pingMainloopTimeout("Main:MiscNativeWindowEvents");
878
879 {
880 LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
881 gViewerWindow->mWindow->processMiscNativeEvents();
882 }
883
899 pingMainloopTimeout("Main:GatherInput"); 884 pingMainloopTimeout("Main:GatherInput");
900 885
901 { 886 {
902 LLFastTimer t2(LLFastTimer::FTM_MESSAGES); 887 LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
903 #if LL_WINDOWS 888 if (!restoreErrorTrap())
904 if (!LLWinDebug::checkExceptionHandler())
905 { 889 {
906 llwarns << " Someone took over my exception handler (post messagehandling)!" << llendl; 890 llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl;
907 } 891 }
908 #endif
909 892
910 gViewerWindow->mWindow->gatherInput(); 893 gViewerWindow->mWindow->gatherInput();
911 } 894 }
@@ -961,7 +944,7 @@ bool LLAppViewer::mainLoop()
961 944
962 resumeMainloopTimeout(); 945 resumeMainloopTimeout();
963 } 946 }
964 947
965 if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) 948 if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
966 { 949 {
967 pauseMainloopTimeout(); 950 pauseMainloopTimeout();
@@ -1183,17 +1166,24 @@ bool LLAppViewer::cleanup()
1183 1166
1184 llinfos << "Global stuff deleted" << llendflush; 1167 llinfos << "Global stuff deleted" << llendflush;
1185 1168
1186#if (!defined(LL_FMOD)) || (!LL_RELEASE_FOR_DOWNLOAD)
1187 // OpenAL likes to crash on exit if we *don't* explicitly shut it down.
1188 if (gAudiop) 1169 if (gAudiop)
1189 { 1170 {
1190 gAudiop->shutdown(); 1171 bool want_longname = false;
1172 if (gAudiop->getDriverName(want_longname) == "FMOD")
1173 {
1174 // This hack exists because fmod likes to occasionally
1175 // hang forever when shutting down, for no apparent
1176 // reason.
1177 llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
1178 }
1179 else
1180 {
1181 gAudiop->shutdown();
1182 }
1183
1184 delete gAudiop;
1185 gAudiop = NULL;
1191 } 1186 }
1192#else
1193 // This hack exists because fmod likes to occasionally hang forever
1194 // when shutting down for no apparent reason.
1195 llwarns << "Hack, skipping audio engine cleanup" << llendflush;
1196#endif
1197 1187
1198 // Note: this is where LLFeatureManager::getInstance()-> used to be deleted. 1188 // Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
1199 1189
@@ -1204,9 +1194,6 @@ bool LLAppViewer::cleanup()
1204 cleanupSavedSettings(); 1194 cleanupSavedSettings();
1205 llinfos << "Settings patched up" << llendflush; 1195 llinfos << "Settings patched up" << llendflush;
1206 1196
1207 delete gAudiop;
1208 gAudiop = NULL;
1209
1210 // delete some of the files left around in the cache. 1197 // delete some of the files left around in the cache.
1211 removeCacheFiles("*.wav"); 1198 removeCacheFiles("*.wav");
1212 removeCacheFiles("*.tmp"); 1199 removeCacheFiles("*.tmp");
@@ -1375,12 +1362,15 @@ bool LLAppViewer::cleanup()
1375 delete sImageDecodeThread; 1362 delete sImageDecodeThread;
1376 sImageDecodeThread = NULL; 1363 sImageDecodeThread = NULL;
1377 1364
1365 //Note:
1366 //LLViewerMedia::cleanupClass() has to be put before gImageList.shutdown()
1367 //because some new image might be generated during cleaning up media. --bao
1368 LLViewerMedia::cleanupClass();
1378 gImageList.shutdown(); // shutdown again in case a callback added something 1369 gImageList.shutdown(); // shutdown again in case a callback added something
1379 LLUIImageList::getInstance()->cleanUp(); 1370 LLUIImageList::getInstance()->cleanUp();
1380 1371
1381 // This should eventually be done in LLAppViewer 1372 // This should eventually be done in LLAppViewer
1382 LLImageJ2C::closeDSO(); 1373 LLImage::cleanupClass();
1383 LLImageFormatted::cleanupClass();
1384 LLVFSThread::cleanupClass(); 1374 LLVFSThread::cleanupClass();
1385 LLLFSThread::cleanupClass(); 1375 LLLFSThread::cleanupClass();
1386 1376
@@ -1401,14 +1391,17 @@ bool LLAppViewer::cleanup()
1401 LLWatchdog::getInstance()->cleanup(); 1391 LLWatchdog::getInstance()->cleanup();
1402 1392
1403 end_messaging_system(); 1393 end_messaging_system();
1394 llinfos << "Message system deleted." << llendflush;
1404 1395
1405 // *NOTE:Mani - The following call is not thread safe. 1396 // *NOTE:Mani - The following call is not thread safe.
1406 LLCurl::cleanupClass(); 1397 LLCurl::cleanupClass();
1398 llinfos << "LLCurl cleaned up." << llendflush;
1407 1399
1408 // If we're exiting to launch an URL, do that here so the screen 1400 // If we're exiting to launch an URL, do that here so the screen
1409 // is at the right resolution before we launch IE. 1401 // is at the right resolution before we launch IE.
1410 if (!gLaunchFileOnQuit.empty()) 1402 if (!gLaunchFileOnQuit.empty())
1411 { 1403 {
1404 llinfos << "Launch file on quit." << llendflush;
1412#if LL_WINDOWS 1405#if LL_WINDOWS
1413 // Indicate an application is starting. 1406 // Indicate an application is starting.
1414 SetCursor(LoadCursor(NULL, IDC_WAIT)); 1407 SetCursor(LoadCursor(NULL, IDC_WAIT));
@@ -1418,9 +1411,8 @@ bool LLAppViewer::cleanup()
1418 ms_sleep(1000); 1411 ms_sleep(1000);
1419 1412
1420 LLWeb::loadURLExternal( gLaunchFileOnQuit ); 1413 LLWeb::loadURLExternal( gLaunchFileOnQuit );
1414 llinfos << "File launched." << llendflush;
1421 } 1415 }
1422
1423 LLViewerMedia::cleanupClass();
1424 1416
1425 llinfos << "Goodbye" << llendflush; 1417 llinfos << "Goodbye" << llendflush;
1426 1418
@@ -1428,6 +1420,25 @@ bool LLAppViewer::cleanup()
1428 return true; 1420 return true;
1429} 1421}
1430 1422
1423// A callback for llerrs to call during the watchdog error.
1424void watchdog_llerrs_callback(const std::string &error_string)
1425{
1426 gLLErrorActivated = true;
1427
1428#ifdef LL_WINDOWS
1429 RaiseException(0,0,0,0);
1430#else
1431 raise(SIGQUIT);
1432#endif
1433}
1434
1435// A callback for the watchdog to call.
1436void watchdog_killer_callback()
1437{
1438 LLError::setFatalFunction(watchdog_llerrs_callback);
1439 llerrs << "Watchdog killer event" << llendl;
1440}
1441
1431bool LLAppViewer::initThreads() 1442bool LLAppViewer::initThreads()
1432{ 1443{
1433#if MEM_TRACK_MEM 1444#if MEM_TRACK_MEM
@@ -1437,10 +1448,11 @@ bool LLAppViewer::initThreads()
1437#endif 1448#endif
1438 1449
1439 const S32 NEVER_SUBMIT_REPORT = 2; 1450 const S32 NEVER_SUBMIT_REPORT = 2;
1440 if(TRUE == gSavedSettings.getBOOL("WatchdogEnabled") 1451 bool use_watchdog = gSavedSettings.getBOOL("WatchdogEnabled");
1441 && (gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT)) 1452 bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT;
1453 if(use_watchdog && send_reports)
1442 { 1454 {
1443 LLWatchdog::getInstance()->init(); 1455 LLWatchdog::getInstance()->init(watchdog_killer_callback);
1444 } 1456 }
1445 1457
1446 LLVFSThread::initClass(enable_threads && true); 1458 LLVFSThread::initClass(enable_threads && true);
@@ -1450,8 +1462,7 @@ bool LLAppViewer::initThreads()
1450 LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true); 1462 LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true);
1451 LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); 1463 LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
1452 LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false); 1464 LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false);
1453 LLImageWorker::initClass(LLAppViewer::getImageDecodeThread()); 1465 LLImage::initClass(LLAppViewer::getImageDecodeThread());
1454 LLImageJ2C::openDSO();
1455 1466
1456 // *FIX: no error handling here! 1467 // *FIX: no error handling here!
1457 return true; 1468 return true;
@@ -1883,22 +1894,6 @@ bool LLAppViewer::initConfiguration()
1883 // llerrs << "Failed to parse skin definition." << llendl; 1894 // llerrs << "Failed to parse skin definition." << llendl;
1884 // } 1895 // }
1885 1896
1886 // LLXmlTreeNode* rootp = skin_def_tree.getRoot();
1887 // LLXmlTreeNode* disabled_message_node = rootp->getChildByName("disabled_message");
1888 // if (disabled_message_node)
1889 // {
1890 // gDisabledMessage = disabled_message_node->getContents();
1891 // }
1892
1893 // static LLStdStringHandle hide_links_string = LLXmlTree::addAttributeString("hide_links");
1894 // rootp->getFastAttributeBOOL(hide_links_string, gHideLinks);
1895
1896 // // Legacy string. This flag really meant we didn't want to expose references to "Second Life".
1897 // // Just set gHideLinks instead.
1898 // static LLStdStringHandle silent_string = LLXmlTree::addAttributeString("silent_update");
1899 // BOOL silent_update;
1900 // rootp->getFastAttributeBOOL(silent_string, silent_update);
1901 // gHideLinks = (gHideLinks || silent_update);
1902 //} 1897 //}
1903 1898
1904#if LL_DARWIN 1899#if LL_DARWIN
@@ -1951,7 +1946,7 @@ bool LLAppViewer::initConfiguration()
1951#endif 1946#endif
1952 LLStringUtil::truncate(gWindowTitle, 255); 1947 LLStringUtil::truncate(gWindowTitle, 255);
1953 1948
1954 //RN: if we received a URL, hand it off to the existing instance 1949 //RN: if we received a URL, hand it off to the existing instance.
1955 // don't call anotherInstanceRunning() when doing URL handoff, as 1950 // don't call anotherInstanceRunning() when doing URL handoff, as
1956 // it relies on checking a marker file which will not work when running 1951 // it relies on checking a marker file which will not work when running
1957 // out of different directories 1952 // out of different directories
@@ -1966,7 +1961,7 @@ bool LLAppViewer::initConfiguration()
1966 } 1961 }
1967 if (!slurl.empty()) 1962 if (!slurl.empty())
1968 { 1963 {
1969 if (send_url_to_other_instance(slurl)) 1964 if (sendURLToOtherInstance(slurl))
1970 { 1965 {
1971 // successfully handed off URL to existing instance, exit 1966 // successfully handed off URL to existing instance, exit
1972 return false; 1967 return false;
@@ -1997,7 +1992,7 @@ bool LLAppViewer::initConfiguration()
1997 } 1992 }
1998 1993
1999 initMarkerFile(); 1994 initMarkerFile();
2000 1995
2001#if LL_SEND_CRASH_REPORTS 1996#if LL_SEND_CRASH_REPORTS
2002 if (gLastExecEvent == LAST_EXEC_FROZE) 1997 if (gLastExecEvent == LAST_EXEC_FROZE)
2003 { 1998 {
@@ -2019,52 +2014,8 @@ bool LLAppViewer::initConfiguration()
2019 { 2014 {
2020 llinfos << "Sending crash report." << llendl; 2015 llinfos << "Sending crash report." << llendl;
2021 2016
2022#if LL_WINDOWS 2017 bool report_freeze = true;
2023 std::string exe_path = gDirUtilp->getAppRODataDir(); 2018 handleCrashReporting(report_freeze);
2024 exe_path += gDirUtilp->getDirDelimiter();
2025 exe_path += "win_crash_logger.exe";
2026
2027 std::string arg_string = "-previous ";
2028 // Spawn crash logger.
2029 // NEEDS to wait until completion, otherwise log files will get smashed.
2030 _spawnl(_P_WAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
2031#elif LL_DARWIN
2032 std::string command_str;
2033 command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger ";
2034 command_str += "-previous";
2035 // XXX -- We need to exit fullscreen mode for this to work.
2036 // XXX -- system() also doesn't wait for completion. Hmm...
2037 system(command_str.c_str()); /* Flawfinder: Ignore */
2038#elif LL_LINUX || LL_SOLARIS
2039 std::string cmd =gDirUtilp->getAppRODataDir();
2040 cmd += gDirUtilp->getDirDelimiter();
2041#if LL_LINUX
2042 cmd += "linux-crash-logger.bin";
2043#else // LL_SOLARIS
2044 cmd += "bin/solaris-crash-logger";
2045#endif // LL_LINUX
2046 char* const cmdargv[] =
2047 {(char*)cmd.c_str(),
2048 (char*)"-previous",
2049 NULL};
2050 fflush(NULL); // flush all buffers before the child inherits them
2051 pid_t pid = fork();
2052 if (pid == 0)
2053 { // child
2054 execv(cmd.c_str(), cmdargv); /* Flawfinder: Ignore */
2055 llwarns << "execv failure when trying to start " << cmd << llendl;
2056 _exit(1); // avoid atexit()
2057 } else {
2058 if (pid > 0)
2059 {
2060 // wait for child proc to die
2061 int childExitStatus;
2062 waitpid(pid, &childExitStatus, 0);
2063 } else {
2064 llwarns << "fork failure." << llendl;
2065 }
2066 }
2067#endif
2068 } 2019 }
2069 else 2020 else
2070 { 2021 {
@@ -2228,8 +2179,6 @@ void LLAppViewer::cleanupSavedSettings()
2228 } 2179 }
2229 2180
2230 gSavedSettings.setF32("MapScale", gMapScale ); 2181 gSavedSettings.setF32("MapScale", gMapScale );
2231 gSavedSettings.setF32("MiniMapScale", gMiniMapScale );
2232 gSavedSettings.setBOOL("AsyncKeyboard", gHandleKeysAsync);
2233 gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips); 2182 gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips);
2234 2183
2235 // Some things are cached in LLAgent. 2184 // Some things are cached in LLAgent.
@@ -2271,7 +2220,7 @@ void LLAppViewer::writeSystemInfo()
2271 gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB()); 2220 gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB());
2272 gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB 2221 gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB
2273 gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple(); 2222 gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
2274 2223
2275 // The user is not logged on yet, but record the current grid choice login url 2224 // The user is not logged on yet, but record the current grid choice login url
2276 // which may have been the intended grid. This can b 2225 // which may have been the intended grid. This can b
2277 gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); 2226 gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel();
@@ -2282,6 +2231,13 @@ void LLAppViewer::writeSystemInfo()
2282 gDebugInfo["MainloopThreadID"] = (S32)thread_id; 2231 gDebugInfo["MainloopThreadID"] = (S32)thread_id;
2283#endif 2232#endif
2284 2233
2234 // "CrashNotHandled" is set here, while things are running well,
2235 // in case of a freeze. If there is a freeze, the crash logger will be launched
2236 // and can read this value from the debug_info.log.
2237 // If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
2238 // then the value of "CrashNotHandled" will be set to true.
2239 gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
2240
2285 // Dump some debugging info 2241 // Dump some debugging info
2286 LL_INFOS("SystemInfo") << gCurrentVersion << LL_ENDL; 2242 LL_INFOS("SystemInfo") << gCurrentVersion << LL_ENDL;
2287 2243
@@ -2358,6 +2314,10 @@ void LLAppViewer::handleViewerCrash()
2358 gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); 2314 gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
2359 gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); 2315 gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
2360 gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); 2316 gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
2317 gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
2318 gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
2319 gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) getCurrentRSS() >> 10;
2320
2361 if(gLogoutInProgress) 2321 if(gLogoutInProgress)
2362 { 2322 {
2363 gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; 2323 gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
@@ -2383,6 +2343,9 @@ void LLAppViewer::handleViewerCrash()
2383 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); 2343 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
2384 } 2344 }
2385 2345
2346 // The crash is being handled here so set this value to false.
2347 // Otherwise the crash logger will think this crash was a freeze.
2348 gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
2386 2349
2387 //Write out the crash status file 2350 //Write out the crash status file
2388 //Use marker file style setup, as that's the simplest, especially since 2351 //Use marker file style setup, as that's the simplest, especially since
@@ -2466,24 +2429,23 @@ bool LLAppViewer::anotherInstanceRunning()
2466 { 2429 {
2467 // Another instance is running. Skip the rest of these operations. 2430 // Another instance is running. Skip the rest of these operations.
2468 LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; 2431 LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
2469 return TRUE; 2432 return true;
2470 } 2433 }
2471 if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1) 2434 if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
2472 { 2435 {
2473 apr_file_close(fMarker); 2436 apr_file_close(fMarker);
2474 LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; 2437 LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
2475 return TRUE; 2438 return true;
2476 } 2439 }
2477 // No other instances; we'll lock this file now & delete on quit. 2440 // No other instances; we'll lock this file now & delete on quit.
2478 apr_file_close(fMarker); 2441 apr_file_close(fMarker);
2479 } 2442 }
2480 LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL; 2443 LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL;
2481 return FALSE; 2444 return false;
2482} 2445}
2483 2446
2484void LLAppViewer::initMarkerFile() 2447void LLAppViewer::initMarkerFile()
2485{ 2448{
2486
2487 //First, check for the existence of other files. 2449 //First, check for the existence of other files.
2488 //There are marker files for two different types of crashes 2450 //There are marker files for two different types of crashes
2489 2451
@@ -2738,7 +2700,7 @@ bool LLAppViewer::initCache()
2738 2700
2739 // Init the texture cache 2701 // Init the texture cache
2740 // Allocate 80% of the cache size for textures 2702 // Allocate 80% of the cache size for textures
2741 BOOL read_only = mSecondInstance ? true : false; 2703 BOOL read_only = mSecondInstance ? TRUE : FALSE;
2742 const S32 MB = 1024*1024; 2704 const S32 MB = 1024*1024;
2743 S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB; 2705 S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
2744 const S64 MAX_CACHE_SIZE = 1024*MB; 2706 const S64 MAX_CACHE_SIZE = 1024*MB;
@@ -3539,12 +3501,12 @@ void LLAppViewer::sendLogoutRequest()
3539 if (mLogoutMarkerFile) 3501 if (mLogoutMarkerFile)
3540 { 3502 {
3541 llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl; 3503 llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl;
3504 apr_file_close(mLogoutMarkerFile);
3542 } 3505 }
3543 else 3506 else
3544 { 3507 {
3545 llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl; 3508 llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl;
3546 } 3509 }
3547 apr_file_close(mLogoutMarkerFile);
3548 } 3510 }
3549} 3511}
3550 3512
@@ -3765,6 +3727,11 @@ void LLAppViewer::forceErrorSoftwareException()
3765 throw; 3727 throw;
3766} 3728}
3767 3729
3730void LLAppViewer::forceErrorDriverCrash()
3731{
3732 glDeleteTextures(1, NULL);
3733}
3734
3768void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs) 3735void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
3769{ 3736{
3770 if(!mMainloopTimeout) 3737 if(!mMainloopTimeout)
@@ -3807,6 +3774,11 @@ void LLAppViewer::pauseMainloopTimeout()
3807 3774
3808void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs) 3775void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
3809{ 3776{
3777// if(!restoreErrorTrap())
3778// {
3779// llwarns << "!!!!!!!!!!!!! Its an error trap!!!!" << state << llendl;
3780// }
3781
3810 if(mMainloopTimeout) 3782 if(mMainloopTimeout)
3811 { 3783 {
3812 if(secs < 0.0f) 3784 if(secs < 0.0f)
@@ -3819,3 +3791,42 @@ void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
3819 } 3791 }
3820} 3792}
3821 3793
3794void LLAppViewer::handleLoginComplete()
3795{
3796 initMainloopTimeout("Mainloop Init");
3797
3798 // Store some data to DebugInfo in case of a freeze.
3799 gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
3800
3801 gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
3802 gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
3803 gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
3804 gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
3805
3806 LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
3807 if ( parcel && parcel->getMusicURL()[0])
3808 {
3809 gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
3810 }
3811 if ( parcel && parcel->getMediaURL()[0])
3812 {
3813 gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
3814 }
3815
3816 gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
3817 gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
3818 gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
3819 gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
3820
3821 if(gAgent.getRegion())
3822 {
3823 gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
3824 gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
3825 }
3826
3827 if(LLAppViewer::instance()->mMainloopTimeout)
3828 {
3829 gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
3830 }
3831 writeDebugInfo();
3832}