diff options
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r-- | indra/newview/llappviewer.cpp | 327 |
1 files changed, 180 insertions, 147 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7f4ba2f2d2..512b1dde7f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2,25 +2,31 @@ * @file llappviewer.cpp * @brief The LLAppViewer class definitions * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ @@ -39,11 +45,11 @@ #include "llgroupmgr.h" #include "llagent.h" #include "llagentcamera.h" -#include "llagentlanguage.h" #include "llagentwearables.h" #include "llwindow.h" #include "llviewerstats.h" #include "llmd5.h" +#include "llmeshrepository.h" #include "llpumpio.h" #include "llmimetypes.h" #include "llslurl.h" @@ -73,12 +79,12 @@ #include "llteleporthistory.h" #include "lllocationhistory.h" #include "llfasttimerview.h" +#include "llvector4a.h" +#include "llviewermenufile.h" #include "llvoicechannel.h" #include "llvoavatarself.h" #include "llsidetray.h" -#include "llfeaturemanager.h" -#include "llurlmatch.h" -#include "lltextutil.h" + #include "llweb.h" #include "llsecondlifeurls.h" @@ -100,8 +106,8 @@ // Third party library includes #include <boost/bind.hpp> - #if LL_WINDOWS + #include "llwindebug.h" # include <share.h> // For _SH_DENYWR in initMarkerFile #else # include <sys/file.h> // For initMarkerFile support @@ -189,7 +195,6 @@ #include "llviewerthrottle.h" #include "llparcel.h" #include "llavatariconctrl.h" -#include "llgroupiconctrl.h" // Include for security api initialization #include "llsecapi.h" @@ -329,6 +334,10 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x."; static std::string gWindowTitle; +std::string gLoginPage; +std::vector<std::string> gLoginURIs; +static std::string gHelperURI; + LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; void idle_afk_check() @@ -349,45 +358,6 @@ static void ui_audio_callback(const LLUUID& uuid) } } -bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base) -{ - if(!match || !base || base->getPlainText()) - return false; - - LLUUID match_id = match->getID(); - - LLIconCtrl* icon; - - if(gAgent.isInGroup(match_id, TRUE)) - { - LLGroupIconCtrl::Params icon_params = LLUICtrlFactory::instance().getDefaultParams<LLGroupIconCtrl>(); - icon_params.group_id = match_id; - icon_params.rect = LLRect(0, 16, 16, 0); - icon_params.visible = true; - icon = LLUICtrlFactory::instance().createWidget<LLGroupIconCtrl>(icon_params); - } - else - { - LLAvatarIconCtrl::Params icon_params = LLUICtrlFactory::instance().getDefaultParams<LLAvatarIconCtrl>(); - icon_params.avatar_id = match_id; - icon_params.rect = LLRect(0, 16, 16, 0); - icon_params.visible = true; - icon = LLUICtrlFactory::instance().createWidget<LLAvatarIconCtrl>(icon_params); - } - - LLInlineViewSegment::Params params; - params.force_newline = false; - params.view = icon; - params.left_pad = 4; - params.right_pad = 4; - params.top_pad = -2; - params.bottom_pad = 2; - - base->appendWidget(params," ",false); - - return true; -} - void request_initial_instant_messages() { static BOOL requested = FALSE; @@ -416,8 +386,14 @@ bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue) const S32 NEVER_SUBMIT_REPORT = 2; if(cb == NEVER_SUBMIT_REPORT) { +// LLWatchdog::getInstance()->cleanup(); // SJB: cleaning up a running watchdog thread is unsafe LLAppViewer::instance()->destroyMainloopTimeout(); } + else if(gSavedSettings.getBOOL("WatchdogEnabled") == TRUE) + { + // Don't re-enable the watchdog when we change the setting; this may get called before it's started +// LLWatchdog::getInstance()->init(); + } return true; } @@ -443,7 +419,7 @@ static void settings_to_globals() LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor"); - LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible"); + LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible"); // clamp auto-open time to some minimum usable value LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay")); @@ -612,6 +588,9 @@ bool LLAppViewer::init() // LLFastTimer::reset(); + // initialize SSE options + LLVector4a::initClass(); + // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API gDirUtilp->initAppDirs("SecondLife"); @@ -630,11 +609,6 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; - // write Google Breakpad minidump files to our log directory - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); - logdir += gDirUtilp->getDirDelimiter(); - setMiniDumpDir(logdir); - // Although initLogging() is the right place to mess with // setFatalFunction(), we can't query gSavedSettings until after // initConfiguration(). @@ -924,7 +898,6 @@ bool LLAppViewer::init() } LLViewerMedia::initClass(); - LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; //EXT-7013 - On windows for some locale (Japanese) standard //datetime formatting functions didn't support some parameters such as "weekday". @@ -941,8 +914,6 @@ bool LLAppViewer::init() LLStringOps::sPM = LLTrans::getString("dateTimePM"); } - LLAgentLanguage::init(); - return true; } @@ -955,6 +926,9 @@ static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread"); static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads"); static LLFastTimer::DeclareTimer FTM_IDLE("Idle"); static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); +static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares"); +static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service"); +static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback"); bool LLAppViewer::mainLoop() { @@ -1064,10 +1038,20 @@ bool LLAppViewer::mainLoop() LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP); pingMainloopTimeout("Main:ServicePump"); LLFastTimer t4(FTM_PUMP); - gAres->process(); - // this pump is necessary to make the login screen show up - gServicePump->pump(); - gServicePump->callback(); + { + LLFastTimer t(FTM_PUMP_ARES); + gAres->process(); + } + { + LLFastTimer t(FTM_PUMP_SERVICE); + // this pump is necessary to make the login screen show up + gServicePump->pump(); + + { + LLFastTimer t(FTM_SERVICE_CALLBACK); + gServicePump->callback(); + } + } } resumeMainloopTimeout(); @@ -1278,14 +1262,6 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); - // remove any old breakpad minidump files from the log directory - if (! isError()) - { - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); - logdir += gDirUtilp->getDirDelimiter(); - gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); - } - // *TODO - generalize this and move DSO wrangling to a helper class -brad std::set<struct apr_dso_handle_t *>::const_iterator i; for(i = mPlugins.begin(); i != mPlugins.end(); ++i) @@ -1326,6 +1302,9 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; + // shut down mesh streamer + gMeshRepo.shutdown(); + // Must clean up texture references before viewer window is destroyed. LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); @@ -1600,6 +1579,8 @@ bool LLAppViewer::cleanup() sTextureFetch->shutDownTextureCacheThread() ; sTextureFetch->shutDownImageDecodeThread() ; + LLFilePickerThread::cleanupClass(); + delete sTextureCache; sTextureCache = NULL; delete sTextureFetch; @@ -1723,6 +1704,14 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif + const S32 NEVER_SUBMIT_REPORT = 2; + bool use_watchdog = gSavedSettings.getBOOL("WatchdogEnabled"); + bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT; + if(use_watchdog && send_reports) + { + LLWatchdog::getInstance()->init(watchdog_killer_callback); + } + LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); @@ -1739,6 +1728,11 @@ bool LLAppViewer::initThreads() mFastTimerLogThread->start(); } + // Mesh streaming and caching + gMeshRepo.init(); + + LLFilePickerThread::initClass(); + // *FIX: no error handling here! return true; } @@ -1951,11 +1945,18 @@ bool LLAppViewer::initConfiguration() } #endif + //*FIX:Mani - Set default to disabling watchdog mainloop + // timeout for mac and linux. There is no call stack info + // on these platform to help debug. #ifndef LL_RELEASE_FOR_DOWNLOAD + gSavedSettings.setBOOL("WatchdogEnabled", FALSE); gSavedSettings.setBOOL("QAMode", TRUE ); - gSavedSettings.setS32("WatchdogEnabled", 0); #endif - + +#ifndef LL_WINDOWS + gSavedSettings.setBOOL("WatchdogEnabled", FALSE); +#endif + gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2)); // These are warnings that appear on the first experience of that condition. @@ -2327,7 +2328,17 @@ void LLAppViewer::checkForCrash(void) { #if LL_SEND_CRASH_REPORTS + //*NOTE:Mani The current state of the crash handler has the MacOSX + // sending all crash reports as freezes, in order to let + // the MacOSX CrashRepoter generate stacks before spawning the + // SL crash logger. + // The Linux and Windows clients generate their own stacks and + // spawn the SL crash logger immediately. This may change in the future. +#if LL_DARWIN + if(gLastExecEvent != LAST_EXEC_NORMAL) +#else if (gLastExecEvent == LAST_EXEC_FROZE) +#endif { llinfos << "Last execution froze, requesting to send crash report." << llendl; // @@ -2383,30 +2394,18 @@ bool LLAppViewer::initWindow() gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"), FALSE, ignorePixelDepth); - // Need to load feature table before cheking to start watchdog. - const S32 NEVER_SUBMIT_REPORT = 2; - bool use_watchdog = false; - int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); - if(watchdog_enabled_setting == -1){ - use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); - } - else - { - // The user has explicitly set this setting; always use that value. - use_watchdog = bool(watchdog_enabled_setting); - } - - bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT; - if(use_watchdog && send_reports) - { - LLWatchdog::getInstance()->init(watchdog_killer_callback); - } - LLNotificationsUI::LLNotificationManager::getInstance(); + if (gSavedSettings.getBOOL("FullScreen")) + { + // request to go full screen... which will be delayed until login + gViewerWindow->toggleFullscreen(FALSE); + } + if (gSavedSettings.getBOOL("WindowMaximized")) { gViewerWindow->mWindow->maximize(); + gViewerWindow->getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio")); } if (!gNoRender) @@ -2425,6 +2424,7 @@ bool LLAppViewer::initWindow() gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); gPipeline.init(); + stop_glerror(); gViewerWindow->initGLDefaults(); @@ -2480,10 +2480,11 @@ void LLAppViewer::cleanupSavedSettings() } } - // save window position if not maximized + // save window position if not fullscreen // as we don't track it in callbacks + BOOL fullscreen = gViewerWindow->mWindow->getFullscreen(); BOOL maximized = gViewerWindow->mWindow->getMaximized(); - if (!maximized) + if (!fullscreen && !maximized) { LLCoordScreen window_pos; @@ -2548,15 +2549,6 @@ void LLAppViewer::writeSystemInfo() // If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze, // then the value of "CrashNotHandled" will be set to true. gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; - - // Insert crash host url (url to post crash log to) if configured. This insures - // that the crash report will go to the proper location in the case of a - // prior freeze. - std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); - if(crashHostUrl != "") - { - gDebugInfo["CrashHostUrl"] = crashHostUrl; - } // Dump some debugging info LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") @@ -2578,6 +2570,13 @@ void LLAppViewer::writeSystemInfo() writeDebugInfo(); // Save out debug_info.log early, in case of crash. } +void LLAppViewer::handleSyncViewerCrash() +{ + LLAppViewer* pApp = LLAppViewer::instance(); + // Call to pure virtual, handled by platform specific llappviewer instance. + pApp->handleSyncCrashTrace(); +} + void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; @@ -2601,13 +2600,9 @@ void LLAppViewer::handleViewerCrash() return; } pApp->mReportedCrash = TRUE; - - // Insert crash host url (url to post crash log to) if configured. - std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); - if(crashHostUrl != "") - { - gDebugInfo["CrashHostUrl"] = crashHostUrl; - } + + // Make sure the watchdog gets turned off... +// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what @@ -2639,12 +2634,6 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); - char *minidump_file = pApp->getMiniDumpFilename(); - if(minidump_file && minidump_file[0] != 0) - { - gDebugInfo["MinidumpPath"] = minidump_file; - } - if(gLogoutInProgress) { gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; @@ -2722,6 +2711,10 @@ void LLAppViewer::handleViewerCrash() LLError::logToFile(""); +// On Mac, we send the report on the next run, since we need macs crash report +// for a stack trace, so we have to let it the app fail. +#if !LL_DARWIN + // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) { @@ -2734,6 +2727,8 @@ void LLAppViewer::handleViewerCrash() // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); + +#endif //!LL_DARWIN return; } @@ -3377,6 +3372,13 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; +#if LL_WINDOWS + // Generates the minidump. + LLWinDebug::generateCrashStacks(NULL); +#endif + LLAppViewer::handleSyncViewerCrash(); + LLAppViewer::handleViewerCrash(); + std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" @@ -3389,8 +3391,6 @@ void LLAppViewer::badNetworkHandler() "If the problem continues, see the Tech Support FAQ at: \n" "www.secondlife.com/support"; forceDisconnect(message.str()); - - LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. @@ -3475,6 +3475,10 @@ static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist"); static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region"); static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World"); static LLFastTimer::DeclareTimer FTM_NETWORK("Network"); +static LLFastTimer::DeclareTimer FTM_AGENT_NETWORK("Agent Network"); +static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot"); +static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update"); +static LLFastTimer::DeclareTimer FTM_VLMANAGER("VL Manager"); /////////////////////////////////////////////////////// // idle() @@ -3495,6 +3499,8 @@ void LLAppViewer::idle() LLEventTimer::updateClass(); LLCriticalDamp::updateInterpolants(); LLMortician::updateClass(); + LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify() + F32 dt_raw = idle_timer.getElapsedTimeAndResetF32(); // Cap out-of-control frame times @@ -3545,7 +3551,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(FTM_NETWORK); + LLFastTimer t(FTM_AGENT_NETWORK); // Update spaceserver timeinfo LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC)); @@ -3560,9 +3566,12 @@ void LLAppViewer::idle() gAgent.moveYaw(-1.f); } - // Handle automatic walking towards points - gAgentPilot.updateTarget(); - gAgent.autoPilot(&yaw); + { + LLFastTimer t(FTM_AGENT_AUTOPILOT); + // Handle automatic walking towards points + gAgentPilot.updateTarget(); + gAgent.autoPilot(&yaw); + } static LLFrameTimer agent_update_timer; static U32 last_control_flags; @@ -3573,6 +3582,7 @@ void LLAppViewer::idle() if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND))) { + LLFastTimer t(FTM_AGENT_UPDATE); // Send avatar and camera info last_control_flags = gAgent.getControlFlags(); send_agent_update(TRUE); @@ -3738,7 +3748,7 @@ void LLAppViewer::idle() // { - LLFastTimer t(FTM_NETWORK); + LLFastTimer t(FTM_VLMANAGER); gVLManager.unpackData(); } @@ -3984,6 +3994,11 @@ static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; #endif static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network"); +static LLFastTimer::DeclareTimer FTM_MESSAGE_ACKS("Message Acks"); +static LLFastTimer::DeclareTimer FTM_RETRANSMIT("Retransmit"); +static LLFastTimer::DeclareTimer FTM_TIMEOUT_CHECK("Timeout Check"); +static LLFastTimer::DeclareTimer FTM_DYNAMIC_THROTTLE("Dynamic Throttle"); +static LLFastTimer::DeclareTimer FTM_CHECK_REGION_CIRCUIT("Check Region Circuit"); void LLAppViewer::idleNetwork() { @@ -4034,7 +4049,10 @@ void LLAppViewer::idleNetwork() } // Handle per-frame message system processing. - gMessageSystem->processAcks(); + { + LLFastTimer ftm(FTM_MESSAGE_ACKS); + gMessageSystem->processAcks(); + } #ifdef TIME_THROTTLE_MESSAGES if (total_time >= CheckMessagesMaxTime) @@ -4071,24 +4089,39 @@ void LLAppViewer::idleNetwork() LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); // Retransmit unacknowledged packets. - gXferManager->retransmitUnackedPackets(); - gAssetStorage->checkForTimeouts(); - gViewerThrottle.updateDynamicThrottle(); + { + LLFastTimer ftm(FTM_RETRANSMIT); + gXferManager->retransmitUnackedPackets(); + } + + { + LLFastTimer ftm(FTM_TIMEOUT_CHECK); + gAssetStorage->checkForTimeouts(); + } + + + { + LLFastTimer ftm(FTM_DYNAMIC_THROTTLE); + gViewerThrottle.updateDynamicThrottle(); + } // Check that the circuit between the viewer and the agent's current // region is still alive - LLViewerRegion *agent_region = gAgent.getRegion(); - if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED)) { - LLUUID this_region_id = agent_region->getRegionID(); - bool this_region_alive = agent_region->isAlive(); - if ((mAgentRegionLastAlive && !this_region_alive) // newly dead - && (mAgentRegionLastID == this_region_id)) // same region + LLFastTimer ftm(FTM_CHECK_REGION_CIRCUIT); + LLViewerRegion *agent_region = gAgent.getRegion(); + if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED)) { - forceDisconnect(LLTrans::getString("AgentLostConnection")); + LLUUID this_region_id = agent_region->getRegionID(); + bool this_region_alive = agent_region->isAlive(); + if ((mAgentRegionLastAlive && !this_region_alive) // newly dead + && (mAgentRegionLastID == this_region_id)) // same region + { + forceDisconnect(LLTrans::getString("AgentLostConnection")); + } + mAgentRegionLastID = this_region_id; + mAgentRegionLastAlive = this_region_alive; } - mAgentRegionLastID = this_region_id; - mAgentRegionLastAlive = this_region_alive; } } @@ -4171,7 +4204,7 @@ void LLAppViewer::forceErrorBreakpoint() void LLAppViewer::forceErrorBadMemoryAccess() { S32* crash = NULL; - *crash = 0xDEADBEEF; + *crash = 0xDEADBEEF; return; } |