From 78830a3a403c4884755b237632d78f01d5eaaf44 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Feb 2022 22:10:32 +0200 Subject: [PATCH 01/14] SL-16827 Time slider not working for some music --- .../libvlc/media_plugin_libvlc.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 8e18b5c6a7..46ebbd31c5 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -73,6 +73,7 @@ private: static void display(void* data, void* id); /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */; + void setDurationDirty(); static void eventCallbacks(const libvlc_event_t* event, void* ptr); @@ -213,6 +214,19 @@ void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom) sendMessage(message); } +//////////////////////////////////////////////////////////////////////////////// +// *virtual* +void MediaPluginLibVLC::setDurationDirty() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueReal("current_time", mCurTime); + message.setValueReal("duration", mDuration); + message.setValueReal("current_rate", 1.0f); + + sendMessage(message); +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) @@ -233,6 +247,7 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; parent->mVlcStatus = STATUS_PLAYING; parent->setVolumeVLC(); + parent->setDurationDirty(); break; case libvlc_MediaPlayerPaused: @@ -245,6 +260,8 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) case libvlc_MediaPlayerEndReached: parent->mVlcStatus = STATUS_DONE; + parent->mCurTime = parent->mDuration; + parent->setDurationDirty(); break; case libvlc_MediaPlayerEncounteredError: @@ -253,6 +270,7 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) case libvlc_MediaPlayerTimeChanged: parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f; + parent->setDurationDirty(); break; case libvlc_MediaPlayerPositionChanged: @@ -260,6 +278,7 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) case libvlc_MediaPlayerLengthChanged: parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f; + parent->setDurationDirty(); break; case libvlc_MediaPlayerTitleChanged: @@ -641,7 +660,7 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) if (!libvlc_media_player_is_playing(mLibVLCMediaPlayer)) { // if paused, won't trigger update, update now - setDirty(0, 0, mWidth, mHeight); + setDurationDirty(); } } } From 25922d422ac97121ca426e41eb7b7186bac9b1a0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Feb 2022 22:20:12 +0200 Subject: [PATCH 02/14] SL-16827 Play doesn't start audio if audio reached end --- indra/media_plugins/libvlc/media_plugin_libvlc.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 46ebbd31c5..89144922cc 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -270,6 +270,10 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) case libvlc_MediaPlayerTimeChanged: parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f; + if (parent->mVlcStatus == STATUS_DONE && libvlc_media_player_is_playing(parent->mLibVLCMediaPlayer)) + { + parent->mVlcStatus = STATUS_PLAYING; + } parent->setDurationDirty(); break; @@ -630,6 +634,13 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) { if (mLibVLCMediaPlayer) { + if (mVlcStatus == STATUS_DONE && !libvlc_media_player_is_playing(mLibVLCMediaPlayer)) + { + // stop or vlc will ignore 'play', it will just + // make an MediaPlayerEndReached event even if + // seek was used + libvlc_media_player_stop(mLibVLCMediaPlayer); + } libvlc_media_player_play(mLibVLCMediaPlayer); } } From de72b36aaa2bfb8d3c1ecb10c4e1d3d11345879d Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 10 Feb 2022 18:49:49 +0200 Subject: [PATCH 03/14] SL-16789 FIXED [MAC] only default cursor is shown after nstalling the Viewer in a directory with a non-ASCII name --- indra/llwindow/llwindowmacosx-objc.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index f895c17643..5ec9b017cf 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -100,13 +100,13 @@ const unsigned short *copyFromPBoard() CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + // extra retain on the NSCursor since we want it to live for the lifetime of the app. NSCursor *cursor = [[[NSCursor alloc] initWithImage: [[[NSImage alloc] initWithContentsOfFile: - [NSString stringWithFormat:@"%s", fullpath] + [NSString stringWithUTF8String:fullpath] ]autorelease] hotSpot:NSMakePoint(hotspotX, hotspotY) ]retain]; From 6f49893fb313d0099900a347cac251f8b7bde40e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 11 Feb 2022 15:25:04 +0200 Subject: [PATCH 04/14] SL-1370 Add more memory logging to mesh repository --- indra/llprimitive/llmodel.cpp | 43 ++++++++++++++++++++++++++++++ indra/llprimitive/llmodel.h | 10 +++++++ indra/newview/llmeshrepository.cpp | 31 +++++++-------------- indra/newview/llmeshrepository.h | 5 ++-- indra/newview/llviewerwindow.cpp | 6 +++++ 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 702a1b5238..a2514f4e33 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1500,6 +1500,25 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi return ret; } +U32 LLMeshSkinInfo::sizeBytes() const +{ + U32 res = sizeof(LLUUID); // mMeshID + + res += sizeof(std::vector) + sizeof(std::string) * mJointNames.size(); + for (U32 i = 0; i < mJointNames.size(); ++i) + { + res += mJointNames[i].size(); // actual size, not capacity + } + + res += sizeof(std::vector) + sizeof(S32) * mJointNums.size(); + res += sizeof(std::vector) + 16 * sizeof(float) * mInvBindMatrix.size(); + res += sizeof(std::vector) + 16 * sizeof(float) * mAlternateBindMatrix.size(); + res += 16 * sizeof(float); //mBindShapeMatrix + res += sizeof(float) + 3 * sizeof(bool); + + return res; +} + LLModel::Decomposition::Decomposition(LLSD& data) { fromLLSD(data); @@ -1606,6 +1625,30 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp) } } +U32 LLModel::Decomposition::sizeBytes() const +{ + U32 res = sizeof(LLUUID); // mMeshID + + res += sizeof(LLModel::convex_hull_decomposition) + sizeof(std::vector) * mHull.size(); + for (U32 i = 0; i < mHull.size(); ++i) + { + res += mHull[i].size() * sizeof(LLVector3); + } + + res += sizeof(LLModel::hull) + sizeof(LLVector3) * mBaseHull.size(); + + res += sizeof(std::vector) + sizeof(std::vector) * mMesh.size(); + for (U32 i = 0; i < mMesh.size(); ++i) + { + res += mMesh[i].sizeBytes(); + } + + res += sizeof(std::vector) * 2; + res += mBaseHullMesh.sizeBytes() + mPhysicsShapeMesh.sizeBytes(); + + return res; +} + bool LLModel::Decomposition::hasHullList() const { return !mHull.empty() ; diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 51fa2f8079..ac3dcaa14a 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -45,6 +45,7 @@ public: LLMeshSkinInfo(LLSD& data); void fromLLSD(LLSD& data); LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const; + U32 sizeBytes() const; LLUUID mMeshID; std::vector mJointNames; @@ -102,6 +103,14 @@ public: { return mPositions.empty(); } + + U32 sizeBytes() const + { + U32 res = sizeof(std::vector) * 2; + res += sizeof(LLVector3) * mPositions.size(); + res += sizeof(LLVector3) * mNormals.size(); + return res; + } }; class Decomposition @@ -112,6 +121,7 @@ public: void fromLLSD(LLSD& data); LLSD asLLSD() const; bool hasHullList() const; + U32 sizeBytes() const; void merge(const Decomposition* rhs); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 8080e43383..7aad3a94be 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -383,6 +383,9 @@ U32 LLMeshRepository::sLODPending = 0; U32 LLMeshRepository::sCacheBytesRead = 0; U32 LLMeshRepository::sCacheBytesWritten = 0; +U32 LLMeshRepository::sCacheBytesHeaders = 0; +U32 LLMeshRepository::sCacheBytesSkins = 0; +U32 LLMeshRepository::sCacheBytesDecomps = 0; U32 LLMeshRepository::sCacheReads = 0; U32 LLMeshRepository::sCacheWrites = 0; U32 LLMeshRepository::sMaxLockHoldoffs = 0; @@ -1877,6 +1880,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes LLMutexLock lock(mHeaderMutex); mMeshHeaderSize[mesh_id] = header_size; mMeshHeader[mesh_id] = header; + LLMeshRepository::sCacheBytesHeaders += header_size; } @@ -3019,27 +3023,6 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod) return -1; } -void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) -{ - mThread->mMeshHeader[data.mUUID] = header; - - // we cache the mesh for default parameters - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - volume_params.setSculptID(data.mUUID, LL_SCULPT_TYPE_MESH); - - for (U32 i = 0; i < 4; i++) - { - if (data.mModel[i].notNull()) - { - LLPointer volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i)); - volume->copyVolumeFaces(data.mModel[i]); - volume->setMeshAssetLoaded(TRUE); - } - } - -} - // Handle failed or successful requests for mesh assets. // // Support for 200 responses was added for several reasons. One, @@ -3957,6 +3940,8 @@ void LLMeshRepository::notifyLoadedMeshes() void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) { mSkinMap[info.mMeshID] = info; + // Alternative: We can get skin size from header + sCacheBytesSkins += info.sizeBytes(); skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); if (iter != mLoadingSkins.end()) @@ -3980,10 +3965,14 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom { //just insert decomp into map mDecompositionMap[decomp->mMeshID] = decomp; mLoadingDecompositions.erase(decomp->mMeshID); + sCacheBytesDecomps += decomp->sizeBytes(); } else { //merge decomp with existing entry + sCacheBytesDecomps -= iter->second->sizeBytes(); iter->second->merge(decomp); + sCacheBytesDecomps += iter->second->sizeBytes(); + mLoadingDecompositions.erase(decomp->mMeshID); delete decomp; } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 441264d42f..8a275e7c15 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -553,6 +553,9 @@ public: static U32 sLODProcessing; static U32 sCacheBytesRead; static U32 sCacheBytesWritten; + static U32 sCacheBytesHeaders; + static U32 sCacheBytesSkins; + static U32 sCacheBytesDecomps; static U32 sCacheReads; static U32 sCacheWrites; static U32 sMaxLockHoldoffs; // Maximum sequential locking failures @@ -642,8 +645,6 @@ public: std::queue mPendingPhysicsShapeRequests; U32 mMeshThreadCount; - - void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header); LLMeshRepoThread* mThread; std::vector mUploads; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 92e8f8026d..25f0f8a6ee 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -778,6 +778,12 @@ public: ypos += y_inc; addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Skins/Decompositions Memory", LLMeshRepository::sCacheBytesSkins / (1024.f*1024.f), LLMeshRepository::sCacheBytesDecomps / (1024.f*1024.f))); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.3f MB Mesh Headers Memory", LLMeshRepository::sCacheBytesHeaders / (1024.f*1024.f))); ypos += y_inc; } From 236593e997e931580d3bd3192b12e450c8054b07 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 11 Feb 2022 20:26:00 +0200 Subject: [PATCH 05/14] Revert "SL-14961 Coroutine crash was not reported to bugsplat" Will be replaced with retrow from nat --- indra/llcommon/llapp.h | 4 --- indra/llcommon/llcoros.cpp | 56 +++++++++--------------------- indra/llcommon/llcoros.h | 7 ++-- indra/newview/llappviewerwin32.cpp | 10 ------ indra/newview/llappviewerwin32.h | 2 -- 5 files changed, 19 insertions(+), 60 deletions(-) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index c65fe21c9c..b9ae49aa44 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -286,10 +286,6 @@ 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 75fc0fec99..6a534951ff 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -264,21 +264,8 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) { - // 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 @@ -291,29 +278,29 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, } } -void LLCoros::winlevel(const std::string& name, const callable_t& callable) +void LLCoros::winlevel(const callable_t& callable) { __try { - toplevelTryWrapper(name, callable); + callable(); } - __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) { - // convert to C++ styled exception for handlers other than bugsplat + // convert to C++ styled exception // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack - // - // 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()); + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); throw std::exception(integer_string); } } #endif -void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) +// 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) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -323,12 +310,16 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call // run the code the caller actually wants in the coroutine try { +#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD + winlevel(callable); +#else callable(); +#endif } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -341,25 +332,10 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call { // Any OTHER kind of uncaught exception will cause the viewer to // crash, hopefully informatively. - LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); - // to not modify callstack - throw; + CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); } } -// 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 a94cfca19f..51f7380def 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -292,12 +292,11 @@ 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/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index ee533875b6..6a504bbdbd 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -708,16 +708,6 @@ 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 82b6b0c77c..3e3fc55151 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -43,8 +43,6 @@ public: bool init() override; // Override to do application initialization bool cleanup() override; - void reportCrashToBugsplat(void* pExcepInfo) override; - protected: void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info. void initConsole() override; // Initialize OS level debugging console. From 6c3507d6d358485c2a8e2fc4d915847cbeda3ee3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sun, 16 Dec 2018 14:31:32 -0500 Subject: [PATCH 06/14] SL-10190: Introduce LLCoros::saveException() and rethrow(). This mechanism uses a queue of std::exception_ptrs to transport an (otherwise) uncaught exception from a terminated coroutine to the thread's main fiber. The main loop calls LLCoros::rethrow() just after giving some cycles to ready coroutines that frame. # Conflicts: # indra/llcommon/llcoros.cpp # indra/llcommon/llcoros.h # indra/newview/llappviewer.cpp --- indra/llcommon/llcoros.cpp | 25 ++++++++++++++++++++++--- indra/llcommon/llcoros.h | 29 +++++++++++++++++++++++++++++ indra/newview/llappviewer.cpp | 2 ++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 6a534951ff..a182d305e8 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -35,6 +35,7 @@ // STL headers // std headers #include +#include // external library headers #include #include @@ -214,6 +215,22 @@ std::string LLCoros::logname() return data.mName.empty()? data.getKey() : data.mName; } +void LLCoros::saveException(const std::string& name, std::exception_ptr exc) +{ + mExceptionQueue.emplace(name, exc); +} + +void LLCoros::rethrow() +{ + if (! mExceptionQueue.empty()) + { + ExceptionData front = mExceptionQueue.front(); + mExceptionQueue.pop(); + LL_WARNS("LLCoros") << "Rethrowing exception from coroutine " << front.name << LL_ENDL; + std::rethrow_exception(front.exception); + } +} + void LLCoros::setStackSize(S32 stacksize) { LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; @@ -330,9 +347,11 @@ void LLCoros::toplevel(std::string name, callable_t callable) } catch (...) { - // Any OTHER kind of uncaught exception will cause the viewer to - // crash, hopefully informatively. - CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + // Stash any OTHER kind of uncaught exception in the rethrow() queue + // to be rethrown by the main fiber. + LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " + << name << LL_ENDL; + LLCoros::instance().saveException(name, std::current_exception()); } } diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 51f7380def..59b2b91f96 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -38,6 +38,8 @@ #include "llinstancetracker.h" #include #include +#include +#include // e.g. #include LLCOROS_MUTEX_HEADER #define LLCOROS_MUTEX_HEADER @@ -156,6 +158,19 @@ public: * LLCoros::launch()). */ static std::string getName(); + + /** + * rethrow() is called by the thread's main fiber to propagate an + * exception from any coroutine into the main fiber, where it can engage + * the normal unhandled-exception machinery, up to and including crash + * reporting. + * + * LLCoros maintains a queue of otherwise-uncaught exceptions from + * terminated coroutines. Each call to rethrow() pops the first of those + * and rethrows it. When the queue is empty (normal case), rethrow() is a + * no-op. + */ + void rethrow(); /** * This variation returns a name suitable for log messages: the explicit @@ -298,6 +313,20 @@ private: static void winlevel(const callable_t& callable); #endif static CoroData& get_CoroData(const std::string& caller); + void saveException(const std::string& name, std::exception_ptr exc); + + struct ExceptionData + { + ExceptionData(const std::string& nm, std::exception_ptr exc): + name(nm), + exception(exc) + {} + // name of coroutine that originally threw this exception + std::string name; + // the thrown exception + std::exception_ptr exception; + }; + std::queue mExceptionQueue; S32 mStackSize; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d17498a6ed..0d80ab543e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1471,6 +1471,8 @@ bool LLAppViewer::doFrame() mainloop.post(newFrame); // give listeners a chance to run llcoro::suspend(); + // if one of our coroutines threw an uncaught exception, rethrow it now + LLCoros::instance().rethrow(); if (!LLApp::isExiting()) { From 913bddf18fa33b54cdb6e30ebd290363e33e7f47 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sun, 16 Dec 2018 14:51:39 -0500 Subject: [PATCH 07/14] SL-10190: Slightly reduce conditional clutter in llcoros.{h,cpp}. Rename 'winlevel()' to 'sehandle()'; change it from a static member function to a free function, thus eliminating the conditional in llcoros.h. Elsewhere than Windows, provide a zero-cost pass-through sehandle() implementation, eliminating the conditional in toplevel(). # Conflicts: # indra/llcommon/llcoros.cpp # indra/llcommon/llcoros.h --- indra/llcommon/llcoros.cpp | 22 +++++++++++++++------- indra/llcommon/llcoros.h | 3 --- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index a182d305e8..51cf2138cb 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -277,6 +277,9 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } +namespace +{ + #if LL_WINDOWS static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific @@ -295,7 +298,7 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) } } -void LLCoros::winlevel(const callable_t& callable) +void sehandle(const LLCoros::callable_t& callable) { __try { @@ -312,7 +315,16 @@ void LLCoros::winlevel(const callable_t& callable) } } -#endif +#else // ! LL_WINDOWS + +inline void sehandle(const LLCoros::callable_t& callable) +{ + callable(); +} + +#endif // ! LL_WINDOWS + +} // anonymous namespace // Top-level wrapper around caller's coroutine callable. // Normally we like to pass strings and such by const reference -- but in this @@ -327,11 +339,7 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { -#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD - winlevel(callable); -#else - callable(); -#endif + sehandle(callable); } catch (const Stop& exc) { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 59b2b91f96..966ce03296 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -309,9 +309,6 @@ private: std::string generateDistinctName(const std::string& prefix) const; 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); void saveException(const std::string& name, std::exception_ptr exc); From cedbf23fd19cb8c155b7e18a922a6da3c317ca1a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 17 Dec 2018 09:58:00 -0500 Subject: [PATCH 08/14] SL-10190: Add menu commands to force AV or exception in coroutine. "Bad memory access" and "unhandled exception" are the two categories of error that we expect might be different in a coroutine than in the viewer's main fiber. Without this change, we've had no reliable way to force either of those to occur. This will require translation work for two new menu items. # Conflicts: # indra/newview/skins/default/xui/en/menu_viewer.xml --- indra/newview/llappviewer.cpp | 6 -- indra/newview/llappviewer.h | 1 - indra/newview/llviewermenu.cpp | 55 +++++++++++++------ .../skins/default/xui/en/menu_viewer.xml | 12 +++- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0d80ab543e..680ce209ea 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5566,12 +5566,6 @@ 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 diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 271307f2a3..c057bd82ef 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -154,7 +154,6 @@ 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 diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 01a4bd587d..92bca90aeb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -33,10 +33,11 @@ #include "llviewermenu.h" // linden library includes -#include "llavatarnamecache.h" // IDEVO +#include "llavatarnamecache.h" // IDEVO (I Are Not Men!) +#include "llcombobox.h" +#include "llcoros.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" -#include "llcombobox.h" #include "llinventorypanel.h" #include "llnotifications.h" #include "llnotificationsutil.h" @@ -2379,6 +2380,7 @@ class LLAdvancedForceErrorLlerror : public view_listener_t return true; } }; + class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2388,6 +2390,22 @@ class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t } }; +class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLCoros::instance().launch( + "AdvancedForceErrorBadMemoryAccessCoro", + [](){ + // Wait for one mainloop() iteration, letting the enclosing + // handleEvent() method return. + llcoro::suspend(); + force_error_bad_memory_access(NULL); + }); + return true; + } +}; + class LLAdvancedForceErrorInfiniteLoop : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2406,6 +2424,22 @@ class LLAdvancedForceErrorSoftwareException : public view_listener_t } }; +class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLCoros::instance().launch( + "AdvancedForceErrorSoftwareExceptionCoro", + [](){ + // Wait for one mainloop() iteration, letting the enclosing + // handleEvent() method return. + llcoro::suspend(); + force_error_software_exception(NULL); + }); + return true; + } +}; + class LLAdvancedForceErrorDriverCrash : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2415,15 +2449,6 @@ 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) @@ -8150,11 +8175,6 @@ 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(); @@ -9330,10 +9350,11 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror"); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess"); + view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); + view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro"); 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"); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 073bdfc9bb..add89c4917 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2649,6 +2649,12 @@ function="World.EnvPreset" + + + @@ -2668,10 +2674,10 @@ function="World.EnvPreset" function="Advanced.ForceErrorSoftwareException" /> + label="Force Software Exception in Coroutine" + name="Force Software Exception in Coroutine"> + function="Advanced.ForceErrorSoftwareExceptionCoro" /> Date: Sat, 12 Feb 2022 23:12:36 +0200 Subject: [PATCH 09/14] SL-4488 Fixed ambiguity mapped weights to vertices in uploader Were not displaying and uploading correctly. --- indra/llprimitive/llmodel.cpp | 2 +- indra/newview/llmodelpreview.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index a2514f4e33..a4fd8b3c24 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -834,7 +834,7 @@ LLSD LLModel::writeModel( { LLVector3 pos(face.mPositions[j].getF32ptr()); - weight_list& weights = high->getJointInfluences(pos); + weight_list& weights = model[idx]->getJointInfluences(pos); S32 count = 0; for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter) diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index f12ddb1745..5ee236e07d 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -2400,7 +2400,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) continue; } - LLModel* base_mdl = *base_iter; base_iter++; S32 num_faces = mdl->getNumVolumeFaces(); @@ -2475,7 +2474,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) //find closest weight to vf.mVertices[i].mPosition LLVector3 pos(vf.mPositions[i].getF32ptr()); - const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos); + const LLModel::weight_list& weight_list = mdl->getJointInfluences(pos); llassert(weight_list.size()>0 && weight_list.size() <= 4); // LLModel::loadModel() should guarantee this LLVector4 w(0, 0, 0, 0); From 935c1362a222f192bf913270d01f6c31c16e175b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 14 Feb 2022 22:26:43 +0200 Subject: [PATCH 10/14] Restored SL-14961 SL-14961 works better for windows than rethrow --- indra/llcommon/llapp.h | 4 ++ indra/llcommon/llcoros.cpp | 74 +++++++++++++++++++----------- indra/llcommon/llcoros.h | 6 ++- indra/newview/llappviewerwin32.cpp | 10 ++++ indra/newview/llappviewerwin32.h | 2 + 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index b9ae49aa44..c65fe21c9c 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -286,6 +286,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 51cf2138cb..ca2e7b38d7 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -277,15 +277,25 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } -namespace -{ - #if LL_WINDOWS 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 @@ -298,38 +308,28 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) } } -void sehandle(const LLCoros::callable_t& callable) +void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable) { __try { - callable(); + LLCoros::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 + // + // 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, code: %lu\n", GetExceptionCode()); + sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); throw std::exception(integer_string); } } +#endif -#else // ! LL_WINDOWS - -inline void sehandle(const LLCoros::callable_t& callable) -{ - callable(); -} - -#endif // ! LL_WINDOWS - -} // anonymous namespace - -// 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); @@ -339,12 +339,12 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { - sehandle(callable); + callable(); } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -355,14 +355,36 @@ void LLCoros::toplevel(std::string name, callable_t callable) } catch (...) { +#if LL_WINDOWS + // Any OTHER kind of uncaught exception will cause the viewer to + // crash, SEH handling should catch it and report to bugsplat. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + // to not modify callstack + throw; +#else // Stash any OTHER kind of uncaught exception in the rethrow() queue // to be rethrown by the main fiber. LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " << name << LL_ENDL; LLCoros::instance().saveException(name, std::current_exception()); +#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) +{ +#if LL_WINDOWS + // Because SEH can's have unwinding, need to call a wrapper + // 'try' is inside SEH handling to not catch LLContinue + sehHandle(name, callable); +#else + toplevelTryWrapper(name, callable); +#endif +} + //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 966ce03296..dbff921f16 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -307,7 +307,11 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; - void toplevel(std::string name, callable_t callable); + void toplevelTryWrapper(const std::string& name, const callable_t& callable); +#if LL_WINDOWS + void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper +#endif + void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper struct CoroData; static CoroData& get_CoroData(const std::string& caller); void saveException(const std::string& name, std::exception_ptr exc); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 6a504bbdbd..ee533875b6 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -708,6 +708,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 3e3fc55151..82b6b0c77c 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -43,6 +43,8 @@ public: bool init() override; // Override to do application initialization bool cleanup() override; + void reportCrashToBugsplat(void* pExcepInfo) override; + protected: void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info. void initConsole() override; // Initialize OS level debugging console. From 2f78338aeb3d0297813bc9c9c7a9d75a2055000d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 11 Jun 2020 15:25:35 +0300 Subject: [PATCH 11/14] Debug Fmod with logging --- indra/cmake/Copy3rdPartyLibs.cmake | 6 +++--- indra/cmake/FMODSTUDIO.cmake | 6 +++--- indra/llaudio/llaudioengine_fmodstudio.cpp | 8 ++++++++ indra/llaudio/llstreamingaudio_fmodstudio.cpp | 1 + indra/newview/CMakeLists.txt | 4 ++-- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index b20d23cead..a8ad51fb11 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -87,7 +87,7 @@ if(WINDOWS) if (FMODSTUDIO) set(debug_files ${debug_files} fmodL.dll) - set(release_files ${release_files} fmod.dll) + set(release_files ${release_files} fmodL.dll) endif (FMODSTUDIO) if (OPENAL) @@ -179,7 +179,7 @@ elseif(DARWIN) if (FMODSTUDIO) set(debug_files ${debug_files} libfmodL.dylib) - set(release_files ${release_files} libfmod.dylib) + set(release_files ${release_files} libfmodL.dylib) endif (FMODSTUDIO) elseif(LINUX) @@ -229,7 +229,7 @@ elseif(LINUX) if (FMODSTUDIO) set(debug_files ${debug_files} "libfmodL.so") - set(release_files ${release_files} "libfmod.so") + set(release_files ${release_files} "libfmodL.so") endif (FMODSTUDIO) else(WINDOWS) diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake index 8840354ac6..a58bdf7ef3 100644 --- a/indra/cmake/FMODSTUDIO.cmake +++ b/indra/cmake/FMODSTUDIO.cmake @@ -20,16 +20,16 @@ if (FMODSTUDIO) if (WINDOWS) set(FMODSTUDIO_LIBRARY debug fmodL_vc - optimized fmod_vc) + optimized fmodL_vc) elseif (DARWIN) #despite files being called libfmod.dylib, we are searching for fmod set(FMODSTUDIO_LIBRARY debug fmodL - optimized fmod) + optimized fmodL) elseif (LINUX) set(FMODSTUDIO_LIBRARY debug fmodL - optimized fmod) + optimized fmodL) endif (WINDOWS) set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY}) set(FMODSTUDIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio) diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp index 5450577134..e9d0fbd6d8 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.cpp +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -97,6 +97,14 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons << " expected:" << FMOD_VERSION << LL_ENDL; } + Check_FMOD_Error(result, "FMOD::System::getVersion"); + std::string logfile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "fmod.log"); + result = FMOD::Debug_Initialize(FMOD_DEBUG_LEVEL_LOG, FMOD_DEBUG_MODE_FILE, 0, logfile.c_str()); + if (Check_FMOD_Error(result, "FMOD::System_Create")) + { + LL_WARNS() << "Failed to init logging" << LL_ENDL; + } + // In this case, all sounds, PLUS wind and stream will be software. result = mSystem->setSoftwareChannels(num_channels + 2); Check_FMOD_Error(result, "FMOD::System::setSoftwareChannels"); diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp index 08d19209aa..d6fedb2952 100644 --- a/indra/llaudio/llstreamingaudio_fmodstudio.cpp +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -157,6 +157,7 @@ void LLStreamingAudio_FMODSTUDIO::update() } else if (open_state == FMOD_OPENSTATE_ERROR) { + LL_INFOS() << "getOpenState returned FMOD_OPENSTATE_ERROR" << LL_ENDL; stop(); return; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5a06106de3..4e687d15c8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1870,8 +1870,8 @@ if (WINDOWS) if (FMODSTUDIO) list(APPEND COPY_INPUT_DEPENDENCIES - ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll - ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll + ${SHARED_LIB_STAGING_DIR}/Release/fmodL.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmodL.dll ${SHARED_LIB_STAGING_DIR}/Debug/fmodL.dll ) endif (FMODSTUDIO) From b21c17eee973dc06c1392dd45dbc19c1ce394852 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 11 Jun 2020 16:38:59 +0300 Subject: [PATCH 12/14] Debug Fmod with logging #2 --- indra/newview/viewer_manifest.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 4b4958e1c2..a7392f701f 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -515,7 +515,7 @@ class WindowsManifest(ViewerManifest): if(self.args['configuration'].lower() == 'debug'): self.path("fmodL.dll") else: - self.path("fmod.dll") + self.path("fmodL.dll") if self.args['openal'] == 'ON': # Get openal dll @@ -1050,7 +1050,7 @@ class DarwinManifest(ViewerManifest): dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) else: for libfile in ( - "libfmod.dylib", + "libfmodL.dylib", ): dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) @@ -1512,9 +1512,9 @@ class Linux_i686_Manifest(LinuxManifest): if self.args['fmodstudio'] == 'ON': try: - self.path("libfmod.so.11.7") - self.path("libfmod.so.11") - self.path("libfmod.so") + self.path("libfmodL.so.11.7") + self.path("libfmodL.so.11") + self.path("libfmodL.so") pass except: print "Skipping libfmod.so - not found" From 1f1d762693027a0f6ce7b913bcc8984767e947be Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 28 Feb 2022 13:18:53 +0200 Subject: [PATCH 13/14] SL-16939 FIXED Graphics driver version is not displayed for Portuguese language --- indra/newview/skins/default/xui/pt/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 5fded9228d..efe887f18e 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -47,7 +47,7 @@ Placa de vídeo: [GRAPHICS_CARD_VENDOR] Placa gráfica: [GRAPHICS_CARD] - Versão do driver de vídeo Windows: [GRAPHICS_CARD_VENDOR] + Versão do driver de vídeo Windows: [GRAPHICS_DRIVER_VERSION] Versão do OpenGL: [OPENGL_VERSION] From b4a5bf0e8cf00d3a928d28fae851148aa23c7150 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 1 Mar 2022 13:40:03 +0200 Subject: [PATCH 14/14] merge conflict fix --- indra/newview/llviewerregion.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 5050ac1257..2b65b5f3ac 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -283,13 +283,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) // record that we just entered a new region newRegionEntry(*regionp); - // After a few attempts, continue login. But keep trying to get the caps: - if (impl->mSeedCapAttempts >= impl->mSeedCapMaxAttemptsBeforeLogin && - STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); - } - if (impl->mSeedCapAttempts > impl->mSeedCapMaxAttempts) { // *TODO: Give a user pop-up about this error?