From d41999865fa860f90ed7389176d1affec82c3cf9 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 Aug 2018 20:17:05 +0200 Subject: [PATCH] FIRE-22962: Attempt at fixing the bridge creation crash: Use timer only to signal state change and perform actions during idle callbacks --- indra/newview/fslslbridge.cpp | 80 ++++++++++++++++++++++++++--------- indra/newview/fslslbridge.h | 32 +++++++------- 2 files changed, 77 insertions(+), 35 deletions(-) diff --git a/indra/newview/fslslbridge.cpp b/indra/newview/fslslbridge.cpp index 11693de12f..60b6c96685 100644 --- a/indra/newview/fslslbridge.cpp +++ b/indra/newview/fslslbridge.cpp @@ -93,14 +93,56 @@ FSLSLBridge::FSLSLBridge(): mpBridge(NULL), mIsFirstCallDone(false), mAllowDetach(false), - mFinishCreation(false) + mFinishCreation(false), + mTimerResult(FSLSLBridge::NO_TIMER) { LL_INFOS("FSLSLBridge") << "Constructing FSLSLBridge" << LL_ENDL; mCurrentFullName = llformat("%s%d.%d", FS_BRIDGE_NAME.c_str(), FS_BRIDGE_MAJOR_VERSION, FS_BRIDGE_MINOR_VERSION); + + gIdleCallbacks.addFunction(onIdle, this); } FSLSLBridge::~FSLSLBridge() { + gIdleCallbacks.deleteFunction(onIdle, this); +} + +void FSLSLBridge::onIdle(void* userdata) +{ + FSLSLBridge* instance = static_cast(userdata); + if (instance) + { + switch (instance->mTimerResult) + { + case START_CREATION_FINISHED: + instance->finishCleanUpPreCreation(); + instance->setTimerResult(NO_TIMER); + break; + case CLEANUP_FINISHED: + instance->finishBridge(); + instance->setTimerResult(NO_TIMER); + break; + case REATTACH_FINISHED: + { + LLViewerInventoryItem* inv_object = gInventory.getItem(instance->mReattachBridgeUUID); + if (inv_object && instance->getBridge() && instance->getBridge()->getUUID() == inv_object->getUUID()) + { + LLAttachmentsMgr::instance().addAttachmentRequest(inv_object->getUUID(), FS_BRIDGE_POINT, TRUE, TRUE); + } + instance->mReattachBridgeUUID.setNull(); + instance->setTimerResult(NO_TIMER); + } + break; + case NO_TIMER: + default: + break; + } + } +} + +void FSLSLBridge::setTimerResult(TimerResult result) +{ + mTimerResult = result; } bool FSLSLBridge::lslToViewer(const std::string& message, const LLUUID& fromID, const LLUUID& ownerID) @@ -979,7 +1021,8 @@ void FSLSLBridge::processDetach(LLViewerObject* object, const LLViewerJointAttac if (mFinishCreation) { LL_INFOS("FSLSLBridge") << "Bridge detached to save settings. Starting re-attach timer..." << LL_ENDL; - new FSLSLBridgeReAttachTimer(object->getAttachmentItemID()); + mReattachBridgeUUID = object->getAttachmentItemID(); + new FSLSLBridgeReAttachTimer(); return; } @@ -1325,15 +1368,7 @@ void FSLSLBridge::checkBridgeScriptName() return; } obj->saveScript(gInventory.getItem(mScriptItemID), TRUE, false); - FSLSLBridgeCleanupTimer* objTimer = new FSLSLBridgeCleanupTimer(1.0f); - objTimer->startTimer(); -} - -BOOL FSLSLBridgeCleanupTimer::tick() -{ - stopTimer(); - FSLSLBridge::instance().finishBridge(); - return TRUE; + new FSLSLBridgeCleanupTimer(); } void FSLSLBridge::cleanUpBridge() @@ -1590,16 +1625,21 @@ void FSLSLBridge::detachOtherBridges() } } -BOOL FSLSLBridgeReAttachTimer::tick() +BOOL FSLSLBridgeCleanupTimer::tick() { - LL_INFOS("FSLSLBridge") << "Re-attaching bridge after creation..." << LL_ENDL; - mEventTimer.stop(); - LLViewerInventoryItem* inv_object = gInventory.getItem(mBridgeUUID); - if (inv_object && FSLSLBridge::instance().mpBridge && FSLSLBridge::instance().mpBridge->getUUID() == inv_object->getUUID()) - { - LLAttachmentsMgr::instance().addAttachmentRequest(inv_object->getUUID(), FS_BRIDGE_POINT, TRUE, TRUE); - } - + FSLSLBridge::instance().setTimerResult(FSLSLBridge::CLEANUP_FINISHED); return TRUE; } +BOOL FSLSLBridgeReAttachTimer::tick() +{ + LL_INFOS("FSLSLBridge") << "Re-attaching bridge after creation..." << LL_ENDL; + FSLSLBridge::instance().setTimerResult(FSLSLBridge::REATTACH_FINISHED); + return TRUE; +} + +BOOL FSLSLBridgeStartCreationTimer::tick() +{ + FSLSLBridge::instance().setTimerResult(FSLSLBridge::START_CREATION_FINISHED); + return TRUE; +} diff --git a/indra/newview/fslslbridge.h b/indra/newview/fslslbridge.h index 9916b8b21a..550131aba9 100644 --- a/indra/newview/fslslbridge.h +++ b/indra/newview/fslslbridge.h @@ -54,6 +54,14 @@ class FSLSLBridge : public LLSingleton, public LLVOInventoryListene ~FSLSLBridge(); public: + enum TimerResult + { + START_CREATION_FINISHED, + CLEANUP_FINISHED, + REATTACH_FINISHED, + NO_TIMER + }; + typedef boost::function tCallback; bool lslToViewer(const std::string& message, const LLUUID& fromID, const LLUUID& ownerID); @@ -84,6 +92,9 @@ public: bool canDetach(const LLUUID& item_id); + static void onIdle(void* userdata); + void setTimerResult(TimerResult result); + // from LLVOInventoryListener virtual void inventoryChanged(LLViewerObject* object, LLInventoryObject::object_list_t* inventory, @@ -102,11 +113,14 @@ private: LLUUID mBridgeFolderID; LLUUID mBridgeContainerFolderID; LLUUID mBridgeUUID; + LLUUID mReattachBridgeUUID; // used when re-attachming the bridge after creation bool mIsFirstCallDone; //initialization conversation uuid_vec_t mAllowedDetachables; + TimerResult mTimerResult; + protected: LLViewerInventoryItem* findInvObject(const std::string& obj_name, const LLUUID& catID); LLUUID findFSCategory(); @@ -177,33 +191,21 @@ protected: class FSLSLBridgeCleanupTimer : public LLEventTimer { public: - FSLSLBridgeCleanupTimer(F32 period) : LLEventTimer(period) {} + FSLSLBridgeCleanupTimer() : LLEventTimer(1.f) {} BOOL tick(); - void startTimer() { mEventTimer.start(); } - void stopTimer() { mEventTimer.stop(); } }; class FSLSLBridgeReAttachTimer : public LLEventTimer { public: - FSLSLBridgeReAttachTimer(const LLUUID& bridge_uuid) : - LLEventTimer(5.f), - mBridgeUUID(bridge_uuid) - {} + FSLSLBridgeReAttachTimer() : LLEventTimer(5.f) {} BOOL tick(); - -protected: - LLUUID mBridgeUUID; }; class FSLSLBridgeStartCreationTimer : public LLEventTimer { public: FSLSLBridgeStartCreationTimer() : LLEventTimer(5.f) {} - BOOL tick() - { - FSLSLBridge::instance().finishCleanUpPreCreation(); - return TRUE; - } + BOOL tick(); }; #endif // FS_LSLBRIDGE_H