From 76dd9385f9354fd661d1c7cc1e7c3d9c39355675 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Jul 2025 23:14:24 +0300 Subject: #4315 Crash in GLTF uploader Properly handle importer's crashes in general --- indra/llprimitive/llmodelloader.cpp | 37 +++++++++++++++++++++- indra/newview/gltf/llgltfloader.cpp | 27 +++++++++++++++- indra/newview/llappviewer.cpp | 21 ++++++++++++ indra/newview/llappviewer.h | 1 + indra/newview/llviewermenu.cpp | 16 ++++++++++ .../skins/default/xui/en/floater_model_preview.xml | 2 ++ indra/newview/skins/default/xui/en/menu_viewer.xml | 10 ++++-- 7 files changed, 110 insertions(+), 4 deletions(-) diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index f97ac16a83..a5b5d595a2 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -149,7 +149,42 @@ LLModelLoader::~LLModelLoader() void LLModelLoader::run() { mWarningsArray.clear(); - doLoadModel(); + try + { + doLoadModel(); + } + // Model loader isn't mission critical, so we just log all exceptions + catch (const LLException& e) + { + LL_WARNS("THREAD") << "LLException in model loader: " << e.what() << "" << LL_ENDL; + LLSD args; + args["Message"] = "UnknownException"; + args["FILENAME"] = mFilename; + args["EXCEPTION"] = e.what(); + mWarningsArray.append(args); + setLoadState(ERROR_PARSING); + } + catch (const std::exception& e) + { + LL_WARNS() << "Exception in LLModelLoader::run: " << e.what() << LL_ENDL; + LLSD args; + args["Message"] = "UnknownException"; + args["FILENAME"] = mFilename; + args["EXCEPTION"] = e.what(); + mWarningsArray.append(args); + setLoadState(ERROR_PARSING); + } + catch (...) + { + LOG_UNHANDLED_EXCEPTION("LLModelLoader"); + LLSD args; + args["Message"] = "UnknownException"; + args["FILENAME"] = mFilename; + args["EXCEPTION"] = "Unknown exception"; + mWarningsArray.append(args); + setLoadState(ERROR_PARSING); + } + // todo: we are inside of a thread, push this into main thread worker, // not into doOnIdleOneTime that laks tread safety doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp index 71bfc021d3..bb6a0a590c 100644 --- a/indra/newview/gltf/llgltfloader.cpp +++ b/indra/newview/gltf/llgltfloader.cpp @@ -124,7 +124,32 @@ bool LLGLTFLoader::OpenFile(const std::string &filename) std::string filename_lc(filename); LLStringUtil::toLower(filename_lc); - mGltfLoaded = mGLTFAsset.load(filename, false); + try + { + mGltfLoaded = mGLTFAsset.load(filename, false); + } + catch (const std::exception& e) + { + LL_WARNS() << "Exception in LLModelLoader::run: " << e.what() << LL_ENDL; + LLSD args; + args["Message"] = "ParsingErrorException"; + args["FILENAME"] = filename; + args["EXCEPTION"] = e.what(); + mWarningsArray.append(args); + setLoadState(ERROR_PARSING); + return false; + } + catch (...) + { + LOG_UNHANDLED_EXCEPTION("LLGLTFLoader"); + LLSD args; + args["Message"] = "ParsingErrorException"; + args["FILENAME"] = filename; + args["EXCEPTION"] = "Unknown exception"; + mWarningsArray.append(args); + setLoadState(ERROR_PARSING); + return false; + } if (!mGltfLoaded) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index aea4492223..9872233e98 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5679,6 +5679,27 @@ void LLAppViewer::forceErrorThreadCrash() thread->start(); } +void LLAppViewer::forceExceptionThreadCrash() +{ + class LLCrashTestThread : public LLThread + { + public: + + LLCrashTestThread() : LLThread("Crash logging test thread") + { + } + + void run() + { + throw std::exception(); + } + }; + + LL_WARNS() << "This is a deliberate exception in a thread" << LL_ENDL; + LLCrashTestThread* thread = new LLCrashTestThread(); + thread->start(); +} + void LLAppViewer::initMainloopTimeout(std::string_view state, F32 secs) { if (!mMainloopTimeout) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b4b8e5bac3..bafe952659 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -175,6 +175,7 @@ public: virtual void forceErrorCoroprocedureCrash(); virtual void forceErrorWorkQueueCrash(); virtual void forceErrorThreadCrash(); + virtual void forceExceptionThreadCrash(); // The list is found in app_settings/settings_files.xml // but since they are used explicitly in code, diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 1c9a892a4f..44157d2d2d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -289,6 +289,7 @@ void force_error_coroutine_crash(); void force_error_coroprocedure_crash(); void force_error_work_queue_crash(); void force_error_thread_crash(); +void force_exception_thread_crash(); void handle_force_delete(); void print_object_info(); @@ -2663,6 +2664,15 @@ class LLAdvancedForceErrorThreadCrash : public view_listener_t } }; +class LLAdvancedForceExceptionThreadCrash : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + force_exception_thread_crash(); + return true; + } +}; + class LLAdvancedForceErrorDisconnectViewer : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -8696,6 +8706,11 @@ void force_error_thread_crash() LLAppViewer::instance()->forceErrorThreadCrash(); } +void force_exception_thread_crash() +{ + LLAppViewer::instance()->forceExceptionThreadCrash(); +} + class LLToolsUseSelectionForGrid : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -9898,6 +9913,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedForceErrorCoroprocedureCrash(), "Advanced.ForceErrorCoroprocedureCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorWorkQueueCrash(), "Advanced.ForceErrorWorkQueueCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash"); + view_listener_t::addMenu(new LLAdvancedForceExceptionThreadCrash(), "Advanced.ForceExceptionThreadCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer"); // Advanced (toplevel) diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index af6e4e8613..618d0a7fda 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -61,6 +61,7 @@ Document has no root Document has no visual_scene Unable to process mesh without position data. Invalid model. + Importer crashed while processing [FILENAME], if you encounter this and file is valid, please report the issue to Second Life Support. Exception: [EXCEPTION]. No scenes defined in GLTF file @@ -80,6 +81,7 @@ Model [MODEL_NAME] contains [SUBMODEL_COUNT] generated mesh parts, parts were trimmed to [SUBMODEL_LIMIT] Buffer is either missing or empty [BUFFER_NAME]. Buffer is either missing or empty. Check presence of [BUFFER_URI] file. + Parser failed to process [FILENAME], file might be corrupt, incomplete or protected from reading. Exception: [EXCEPTION]. + label="Force an LLError Crash in a Thread" + name="Force an LLError Crash in a Thread"> + + + -- cgit v1.2.3