diff --git a/autobuild.xml b/autobuild.xml index 33423b31ef..b2b2a4bf69 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2405,18 +2405,18 @@ archive hash - c541838a933e0714a954e9ef6c89345d + 0a6349b11c8e9d34f0c80b8081736e75 hash_algorithm md5 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/73387/708088/llca-202012011600.553112-common-553112.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/79438/751815/llca-202104010215.557744-common-557744.tar.bz2 name common version - 202012011600.553112 + 202104010215.557744 llphysicsextensions_source diff --git a/doc/contributions.txt b/doc/contributions.txt index 6a47b53121..9a42f9164f 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -265,10 +265,11 @@ Benja Kepler Benjamin Bigdipper Beq Janus BUG-227094 -Beth Walcher -Beq Janus SL-10288 SL-13583 + SL-14766 + SL-14927 +Beth Walcher Bezilon Kasei Biancaluce Robbiani CT-225 diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 245c73e3a2..5fa91b8bf5 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -259,6 +259,10 @@ public: */ LLRunner& getRunner() { return mRunner; } +#ifdef LL_WINDOWS + virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { } +#endif + public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 2f1ca791ed..3a7ab0901e 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -254,8 +254,21 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) { + // C++ exceptions were logged in toplevelTryWrapper, but not SEH + // log SEH exceptions here, to make sure it gets into bugsplat's + // report and because __try won't allow std::string operations + if (code != STATUS_MSC_EXCEPTION) + { + LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; + } + // Handle bugsplat here, since GetExceptionInformation() can only be + // called from within filter for __except(filter), not from __except's {} + // Bugsplat should get all exceptions, C++ and SEH + LLApp::instance()->reportCrashToBugsplat(exception_infop); + + // Only convert non C++ exceptions. if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on @@ -268,29 +281,29 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) } } -void LLCoros::winlevel(const callable_t& callable) +void LLCoros::winlevel(const std::string& name, const callable_t& callable) { __try { - callable(); + toplevelTryWrapper(name, callable); } - __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) { - // convert to C++ styled exception + // convert to C++ styled exception for handlers other than bugsplat // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack - char integer_string[32]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + // + // in case of bugsplat this will get to exceptionTerminateHandler and + // looks like fiber will terminate application after that + char integer_string[512]; + sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); throw std::exception(integer_string); } } #endif -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) +void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -300,18 +313,12 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { -// Disable for more meaningful callstacks -//#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD -// winlevel(callable); -//#else callable(); -//#endif -// Disable for more meaningful callstacks } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -324,10 +331,25 @@ void LLCoros::toplevel(std::string name, callable_t callable) { // Any OTHER kind of uncaught exception will cause the viewer to // crash, hopefully informatively. - CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + // to not modify callstack + throw; } } +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable) +{ +#if LL_WINDOWS + // Can not use __try in functions that require unwinding, so use one more wrapper + winlevel(name, callable); +#else + toplevelTryWrapper(name, callable); +#endif +} + //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 38c2356c99..6c0bec3ef9 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -290,11 +290,12 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; +#if LL_WINDOWS + void winlevel(const std::string& name, const callable_t& callable); +#endif + void toplevelTryWrapper(const std::string& name, const callable_t& callable); void toplevel(std::string name, callable_t callable); struct CoroData; -#if LL_WINDOWS - static void winlevel(const callable_t& callable); -#endif static CoroData& get_CoroData(const std::string& caller); S32 mStackSize; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index c897130e5e..64d702a612 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1723,7 +1723,7 @@ void LLFolderViewFolder::destroyView() // extractItem() removes the specified item from the folder, but // doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) +void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model ) { if (item->isSelected()) getRoot()->clearSelection(); @@ -1746,7 +1746,11 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) mItems.erase(it); } //item has been removed, need to update filter - getViewModelItem()->removeChild(item->getViewModelItem()); + if (deparent_model) + { + // in some cases model does not belong to parent view, is shared between views + getViewModelItem()->removeChild(item->getViewModelItem()); + } //because an item is going away regardless of filter status, force rearrange requestArrange(); removeChild(item); diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 7baf88a629..72bb926163 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -402,7 +402,7 @@ public: // extractItem() removes the specified item from the folder, but // doesn't delete it. - virtual void extractItem( LLFolderViewItem* item ); + virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true); // This function is called by a child that needs to be resorted. void resort(LLFolderViewItem* item); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f84e980fba..d41e5ccb93 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1039,25 +1039,14 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal } // static -// FIRE-30774 displayname capability is targetting previous region -// void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id) -// { -// LLViewerRegion* region = gAgent.getRegion(); -// if (region && region->getRegionID() == region_id) -// { -// region->requestSimulatorFeatures(); -// LLAppViewer::instance()->updateNameLookupUrl(); -// } -// } -void LLAgent::capabilityReceivedCallback(LLViewerRegion* regionp) +void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp) { - if (regionp) + if (regionp && regionp->getRegionID() == region_id) { regionp->requestSimulatorFeatures(); LLAppViewer::instance()->updateNameLookupUrl(regionp); } } -// //----------------------------------------------------------------------------- // setRegion() @@ -1109,17 +1098,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (regionp->capabilitiesReceived()) { regionp->requestSimulatorFeatures(); - // FIRE-30774 displayname capability is targetting previous region - // LLAppViewer::instance()->updateNameLookupUrl(); LLAppViewer::instance()->updateNameLookupUrl(regionp); - // } else { - // FIRE-30774 displayname capability is targetting previous region - // regionp->setCapabilitiesReceivedCallback(LLAgent::capabilityReceivedCallback); - regionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::capabilityReceivedCallback, regionp)); - // + regionp->setCapabilitiesReceivedCallback(LLAgent::capabilityReceivedCallback); } } @@ -1141,17 +1124,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (regionp->capabilitiesReceived()) { - // FIRE-30774 displayname capability is targetting previous region - // LLAppViewer::instance()->updateNameLookupUrl(); LLAppViewer::instance()->updateNameLookupUrl(regionp); - // } else { - // FIRE-30774 displayname capability is targetting previous region - // regionp->setCapabilitiesReceivedCallback([regionp](const LLUUID ®ion_id) {LLAppViewer::instance()->updateNameLookupUrl(); }); - regionp->setCapabilitiesReceivedCallback([regionp](const LLUUID ®ion_id) { LLAppViewer::instance()->updateNameLookupUrl(regionp); }); - // + regionp->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id, LLViewerRegion* regionp) {LLAppViewer::instance()->updateNameLookupUrl(regionp); }); } } diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 7c0e6c141a..586c7b03bb 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -258,10 +258,7 @@ public: boost::signals2::connection addParcelChangedCallback(parcel_changed_callback_t); private: - // FIRE-30774 displayname capability is targetting previous region - // static void capabilityReceivedCallback(const LLUUID ®ion_id); - static void capabilityReceivedCallback(LLViewerRegion* regionp); - // + static void capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp); typedef boost::signals2::signal parcel_changed_signal_t; parcel_changed_signal_t mParcelChangedSignal; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a7429e30d2..1c6418f6bb 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -6042,13 +6042,9 @@ void LLAppViewer::sendLogoutRequest() } } -// FIRE-30774 displayname capability is targetting previous region -// void LLAppViewer::updateNameLookupUrl() -void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * region) -// +void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp) { - // LLViewerRegion* region = gAgent.getRegion(); - if (!region || !region->capabilitiesReceived()) + if (!regionp || !regionp->capabilitiesReceived()) { return; } @@ -6057,7 +6053,7 @@ void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * region) bool had_capability = name_cache->hasNameLookupURL(); std::string name_lookup_url; name_lookup_url.reserve(128); // avoid a memory allocation below - name_lookup_url = region->getCapability("GetDisplayNames"); + name_lookup_url = regionp->getCapability("GetDisplayNames"); bool have_capability = !name_lookup_url.empty(); if (have_capability) { @@ -6405,6 +6401,33 @@ void LLAppViewer::forceErrorDriverCrash() glDeleteTextures(1, NULL); } +void LLAppViewer::forceErrorCoroutineCrash() +{ + LL_WARNS() << "Forcing a crash in LLCoros" << LL_ENDL; + LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw LLException("A deliberate crash from LLCoros"); }); +} + +void LLAppViewer::forceErrorThreadCrash() +{ + class LLCrashTestThread : public LLThread + { + public: + + LLCrashTestThread() : LLThread("Crash logging test thread") + { + } + + void run() + { + LL_ERRS() << "This is a deliberate llerror in thread" << LL_ENDL; + } + }; + + LL_WARNS() << "This is a deliberate crash in a thread" << LL_ENDL; + LLCrashTestThread *thread = new LLCrashTestThread(); + thread->start(); +} + // Change from std::string to char const*, saving a lot of object construction/destruction per frame //void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs) void LLAppViewer::initMainloopTimeout( char const* state, F32 secs) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 400c4b494a..2d17c882bc 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -58,7 +58,7 @@ class LLImageDecodeThread; class LLTextureFetch; class LLWatchdogTimeout; class LLViewerJoystick; -class LLViewerRegion; // +class LLViewerRegion; extern LLTrace::BlockTimerStatHandle FTM_FRAME; @@ -149,6 +149,8 @@ public: virtual void forceErrorInfiniteLoop(); virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); + virtual void forceErrorCoroutineCrash(); + virtual void forceErrorThreadCrash(); // The list is found in app_settings/settings_files.xml // but since they are used explicitly in code, @@ -223,10 +225,7 @@ public: // llcorehttp init/shutdown/config information. LLAppCoreHttp & getAppCoreHttp() { return mAppCoreHttp; } - // FIRE-30774 displayname capability is targetting previous region - // void updateNameLookupUrl(); - void updateNameLookupUrl( const LLViewerRegion * region ); - // + void updateNameLookupUrl(const LLViewerRegion* regionp); protected: virtual bool initWindow(); // Initialize the viewer's window. diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 818e09999f..a40cb7de2f 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -784,6 +784,13 @@ bool LLAppViewerWin32::init() #else // LL_BUGSPLAT #pragma message("Building with BugSplat") // Pre BugSplat dance, make sure settings are valid, query crash behavior and then set up Bugsplat accordingly" + //if (!isSecondInstance()) + //{ + // // Cleanup previous session + // std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log"); + // LLFile::remove(log_file, ENOENT); + //} + success = LLAppViewer::init(); if (!success) return false; @@ -812,7 +819,7 @@ bool LLAppViewerWin32::init() llifstream inf(build_data_fname.c_str()); if (! inf.is_open()) { - LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname + LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname << "'" << LL_ENDL; } else @@ -822,7 +829,7 @@ bool LLAppViewerWin32::init() if (! reader.parse(inf, build_data, false)) // don't collect comments { // gah, the typo is baked into Json::Reader API - LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname + LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname << "': " << reader.getFormatedErrorMessages() << LL_ENDL; } else @@ -830,7 +837,7 @@ bool LLAppViewerWin32::init() Json::Value BugSplat_DB = build_data["BugSplat DB"]; if (! BugSplat_DB) { - LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" + LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" << build_data_fname << "'" << LL_ENDL; } else @@ -841,31 +848,40 @@ bool LLAppViewerWin32::init() LL_VIEWER_VERSION_PATCH << '.' << LL_VIEWER_VERSION_BUILD)); - // have to convert normal wide strings to strings of __wchar_t - // Set up Bugsplat to ask or always send + //DWORD dwFlags = MDSF_NONINTERACTIVE | // automatically submit report without prompting + // MDSF_PREVENTHIJACKING; // disallow swiping Exception filter + DWORD dwFlags = dwAsk | + MDSF_PREVENTHIJACKING; // disallow swiping Exception filter + // - // sBugSplatSender = new MiniDmpSender( - // WCSTR(BugSplat_DB.asString()), - // WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)), - // WCSTR(version_string), - // nullptr, // szAppIdentifier -- set later - // MDSF_NONINTERACTIVE | // automatically submit report without prompting - // MDSF_PREVENTHIJACKING); // disallow swiping Exception filter - + //bool needs_log_file = !isSecondInstance() && debugLoggingEnabled("BUGSPLAT"); + //if (needs_log_file) + //{ + // // Startup only! + // LL_INFOS("BUGSPLAT") << "Engaged BugSplat logging to bugsplat.log" << LL_ENDL; + // dwFlags |= MDSF_LOGFILE | MDSF_LOG_VERBOSE; + //} + + // have to convert normal wide strings to strings of __wchar_t sBugSplatSender = new MiniDmpSender( WCSTR(BugSplat_DB.asString()), WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)), WCSTR(version_string), nullptr, // szAppIdentifier -- set later - dwAsk | - MDSF_PREVENTHIJACKING); // disallow swiping Exception filter - // + dwFlags); sBugSplatSender->setCallback(bugsplatSendLog); + //if (needs_log_file) + //{ + // // Log file will be created in %TEMP%, but it will be moved into logs folder in case of crash + // std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log"); + // sBugSplatSender->setLogFilePath(WCSTR(log_file)); + //} + // engage stringize() overload that converts from wstring - LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) + LL_INFOS("BUGSPLAT") << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) << ' ' << stringize(version_string) << ')' << LL_ENDL; } // got BugSplat_DB } // parsed build_data.json @@ -899,6 +915,16 @@ bool LLAppViewerWin32::cleanup() return result; } +void LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo) +{ +#if defined(LL_BUGSPLAT) + if (sBugSplatSender) + { + sBugSplatSender->createReport((EXCEPTION_POINTERS*)pExcepInfo); + } +#endif // LL_BUGSPLAT +} + void LLAppViewerWin32::initLoggingAndGetLastDuration() { LLAppViewer::initLoggingAndGetLastDuration(); diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 9f0b6aaf95..ca271af7a0 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -40,20 +40,22 @@ public: // // Main application logic // - virtual bool init(); // Override to do application initialization - virtual bool cleanup(); + bool init() override; // Override to do application initialization + bool cleanup() override; + + void reportCrashToBugsplat(void* pExcepInfo) override; protected: - virtual void initLoggingAndGetLastDuration(); // Override to clean stack_trace info. - virtual void initConsole(); // Initialize OS level debugging console. - virtual bool initHardwareTest(); // Win32 uses DX9 to test hardware. - virtual bool initParseCommandLine(LLCommandLineParser& clp); + void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info. + void initConsole() override; // Initialize OS level debugging console. + bool initHardwareTest() override; // Win32 uses DX9 to test hardware. + bool initParseCommandLine(LLCommandLineParser& clp) override; - virtual bool beingDebugged(); - virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); + bool beingDebugged() override; + bool restoreErrorTrap() override; + void initCrashReporting(bool reportFreeze) override; - virtual bool sendURLToOtherInstance(const std::string& url); + bool sendURLToOtherInstance(const std::string& url) override; std::string generateSerialNumber(); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d176c9647c..e0afe69aab 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -357,7 +357,7 @@ LLConversationItemParticipant* LLConversationItemSession::findParticipant(const for (iter = mChildren.begin(); iter != mChildren.end(); iter++) { participant = dynamic_cast(*iter); - if (participant->hasSameValue(participant_id)) + if (participant && participant->hasSameValue(participant_id)) { break; } @@ -468,7 +468,7 @@ const bool LLConversationItemSession::getTime(F64& time) const { participant = dynamic_cast(*iter); F64 participant_time; - if (participant->getTime(participant_time)) + if (participant && participant->getTime(participant_time)) { has_time = true; most_recent_time = llmax(most_recent_time,participant_time); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 0cf9ea6dfd..7708e18cdc 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -619,10 +619,13 @@ void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); - participant_model->resetRefresh(); - - // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat - mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); + if (participant_model) + { + participant_model->resetRefresh(); + + // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat + mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); + } // Do the regular upstream refresh LLFolderViewItem::refresh(); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index f9827a5e25..a1c69d1bd5 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1110,7 +1110,7 @@ void LLEnvironment::onRegionChange() } if (!cur_region->capabilitiesReceived()) { - cur_region->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id) { LLEnvironment::instance().requestRegion(); }); + cur_region->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id, LLViewerRegion* regionp) { LLEnvironment::instance().requestRegion(); }); return; } requestRegion(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 59d5f72146..dc7ae539f8 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -63,7 +63,9 @@ #include "boost/foreach.hpp" -const S32 EVENTS_PER_IDLE_LOOP = 100; +const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80; +const S32 EVENTS_PER_IDLE_LOOP_BACKGROUND = 40; +const F32 EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE = 0.01f; // process a minimum of 1% of total events per frame // // LLFloaterIMContainer @@ -420,8 +422,11 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate() while (current_participant_model != end_participant_model) { LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); - // Get the avatar name for this participant id from the cache and update the model - participant_model->updateName(); + if (participant_model) + { + // Get the avatar name for this participant id from the cache and update the model + participant_model->updateName(); + } // Next participant current_participant_model++; } @@ -468,8 +473,11 @@ void LLFloaterIMContainer::idleUpdate() while (current_participant_model != end_participant_model) { LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); - participant_model->setModeratorOptionsVisible(is_moderator); - participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID); + if (participant_model) + { + participant_model->setModeratorOptionsVisible(is_moderator); + participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID); + } current_participant_model++; } @@ -502,20 +510,49 @@ void LLFloaterIMContainer::idleUpdate() void LLFloaterIMContainer::idleProcessEvents() { - if (!mConversationEventQueue.empty()) - { - S32 events_to_handle = llmin((S32)mConversationEventQueue.size(), EVENTS_PER_IDLE_LOOP); - for (S32 i = 0; i < events_to_handle; i++) - { - handleConversationModelEvent(mConversationEventQueue.back()); - mConversationEventQueue.pop_back(); - } - } + LLUUID current_session_id = getSelectedSession(); + conversations_items_deque::iterator iter = mConversationEventQueue.begin(); + conversations_items_deque::iterator end = mConversationEventQueue.end(); + while (iter != end) + { + std::deque &events = iter->second; + if (!events.empty()) + { + S32 events_to_handle; + S32 query_size = (S32)events.size(); + if (current_session_id == iter->first) + { + events_to_handle = EVENTS_PER_IDLE_LOOP_CURRENT_SESSION; + } + else + { + events_to_handle = EVENTS_PER_IDLE_LOOP_BACKGROUND; + } + + if (events_to_handle <= query_size) + { + // Some groups can be very large and can generate huge amount of updates, scale processing up to keep up + events_to_handle = llmax(events_to_handle, (S32)(query_size * EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE)); + } + else + { + events_to_handle = query_size; + } + + for (S32 i = 0; i < events_to_handle; i++) + { + handleConversationModelEvent(events.back()); + events.pop_back(); + } + } + iter++; + } } bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) { - mConversationEventQueue.push_front(event); + LLUUID id = event.get("session_uuid").asUUID(); + mConversationEventQueue[id].push_front(event); return true; } @@ -1835,6 +1872,8 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c // Suppress the conversation items and widgets from their respective maps mConversationsItems.erase(uuid); mConversationsWidgets.erase(uuid); + // Clear event query (otherwise reopening session in some way can bombard session with stale data) + mConversationEventQueue.erase(uuid); // Don't let the focus fall IW, select and refocus on the first conversation in the list if (change_focus) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 38590666c1..31b551e3e4 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -231,9 +231,10 @@ private: conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; - LLEventStream mConversationsEventStream; + LLEventStream mConversationsEventStream; - std::deque mConversationEventQueue; + typedef std::map > conversations_items_deque; + conversations_items_deque mConversationEventQueue; LLTimer mParticipantRefreshTimer; }; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index ba5679fa7c..ba64d7e4ca 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -494,7 +494,10 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() while (current_participant_model != end_participant_model) { LLConversationItem* participant_model = dynamic_cast(*current_participant_model); - addConversationViewParticipant(participant_model); + if (participant_model) + { + addConversationViewParticipant(participant_model); + } current_participant_model++; } } @@ -531,7 +534,7 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); if (widget) { - mConversationsRoot->extractItem(widget); + mConversationsRoot->extractItem(widget, false); delete widget; } mConversationsWidgets.erase(participant_id); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 676d7b11ad..093fe718b3 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1261,6 +1261,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) httpOpts->setFollowRedirects(true); httpOpts->setWantHeaders(true); + httpOpts->setSSLVerifyPeer(false); // viewer's cert bundle doesn't appear to agree with web certs from "https://my.secondlife.com/" LLURL hostUrl(url.c_str()); std::string hostAuth = hostUrl.getAuthority(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b19aedce8c..40411ff245 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -347,6 +347,8 @@ void force_error_bad_memory_access(void *); void force_error_infinite_loop(void *); void force_error_software_exception(void *); void force_error_driver_crash(void *); +void force_error_coroutine_crash(void *); +void force_error_thread_crash(void *); void handle_force_delete(void*); void print_object_info(void*); @@ -2658,6 +2660,24 @@ class LLAdvancedForceErrorDriverCrash : public view_listener_t } }; +class LLAdvancedForceErrorCoroutineCrash : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + force_error_coroutine_crash(NULL); + return true; + } +}; + +class LLAdvancedForceErrorThreadCrash : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + force_error_thread_crash(NULL); + return true; + } +}; + class LLAdvancedForceErrorDisconnectViewer : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -10257,6 +10277,16 @@ void force_error_driver_crash(void *) LLAppViewer::instance()->forceErrorDriverCrash(); } +void force_error_coroutine_crash(void *) +{ + LLAppViewer::instance()->forceErrorCoroutineCrash(); +} + +void force_error_thread_crash(void *) +{ + LLAppViewer::instance()->forceErrorThreadCrash(); +} + class LLToolsUseSelectionForGrid : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -11840,6 +11870,8 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash"); + view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash"); + view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer"); // Advanced (toplevel) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index daa4200552..fea5ba01a7 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2407,7 +2407,7 @@ void LLViewerRegion::setSimulatorFeaturesReceived(bool received) mSimulatorFeaturesReceived = received; if (received) { - mSimulatorFeaturesReceivedSignal(getRegionID()); + mSimulatorFeaturesReceivedSignal(getRegionID(), this); mSimulatorFeaturesReceivedSignal.disconnect_all_slots(); } } @@ -3421,7 +3421,7 @@ void LLViewerRegion::setCapabilitiesReceived(bool received) // so that they can safely use getCapability(). if (received) { - mCapabilitiesReceivedSignal(getRegionID()); + mCapabilitiesReceivedSignal(getRegionID(), this); LLFloaterPermsDefault::sendInitialPerms(); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 9c1715d6aa..2aa8258a75 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -97,7 +97,7 @@ public: NUM_PARTITIONS } eObjectPartitions; - typedef boost::signals2::signal caps_received_signal_t; + typedef boost::signals2::signal caps_received_signal_t; LLViewerRegion(const U64 &handle, const LLHost &host, diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 9bcee631d6..0d553657d8 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -113,6 +113,7 @@ void LLWebProfile::uploadImageCoro(LLPointer image, std::strin httpOpts->setWantHeaders(true); httpOpts->setFollowRedirects(false); + httpOpts->setSSLVerifyPeer(false); ; // viewer's cert bundle doesn't appear to agree with web certs from "https://my.secondlife.com/" // Get upload configuration data. std::string configUrl(getProfileURL(std::string()) + "snapshots/s3_upload_config"); diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 730aa3774f..d55e1b7cd3 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -51,7 +51,7 @@ bool LLEnvironmentRequest::initiate(LLEnvironment::environment_apply_fn cb) if (!cur_region->capabilitiesReceived()) { LL_INFOS("WindlightCaps") << "Deferring windlight settings request until we've got region caps" << LL_ENDL; - cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID ®ion_id) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); }); + cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID ®ion_id, LLViewerRegion* regionp) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); }); return false; } diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0c14c9fde1..46bb73dfc0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3642,6 +3642,18 @@ + + + + + +