diff options
Diffstat (limited to 'indra')
145 files changed, 2139 insertions, 1107 deletions
| diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 53e5d7b6a5..db88e44127 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -13,6 +13,7 @@ project(${ROOT_PROJECT_NAME})  set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")  include(Variables) +include(bugsplat)  include(BuildVersion)  set(LEGACY_STDIO_LIBS) @@ -50,7 +51,10 @@ endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)  add_custom_target(viewer) +if (NOT USE_BUGSPLAT)  add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger) +endif (NOT USE_BUGSPLAT) +  add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)  add_subdirectory(${LIBS_OPEN_PREFIX}llui)  add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components) @@ -64,29 +68,18 @@ add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)  endif (ENABLE_MEDIA_PLUGINS)  if (LINUX) -  add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)    if (INSTALL_PROPRIETARY)        include(LLAppearanceUtility)        add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR})    endif (INSTALL_PROPRIETARY) -  add_dependencies(viewer linux-crash-logger-strip-target) -elseif (DARWIN) -  add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) -  add_dependencies(viewer mac-crash-logger) -elseif (WINDOWS) -  add_subdirectory(${VIEWER_PREFIX}win_crash_logger) -  # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake -  if (EXISTS ${VIEWER_DIR}win_setup) -    add_subdirectory(${VIEWER_DIR}win_setup) -  endif (EXISTS ${VIEWER_DIR}win_setup) -  # add_dependencies(viewer windows-setup windows-crash-logger) -  add_dependencies(viewer windows-crash-logger)  endif (LINUX) -add_subdirectory(${VIEWER_PREFIX}newview) -add_dependencies(viewer secondlife-bin) - -add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL) +if (WINDOWS) +    # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake +    if (EXISTS ${VIEWER_DIR}win_setup) +      add_subdirectory(${VIEWER_DIR}win_setup) +    endif (EXISTS ${VIEWER_DIR}win_setup) +endif (WINDOWS)  # sets the 'startup project' for debugging from visual studio.  set_property( @@ -94,6 +87,32 @@ set_property(      PROPERTY VS_STARTUP_PROJECT secondlife-bin      ) +if (USE_BUGSPLAT) +    if (BUGSPLAT_DB) +        message(STATUS "Building with BugSplat; database '${BUGSPLAT_DB}'") +    else (BUGSPLAT_DB) +        message(WARNING "Building with BugSplat, but no database name set (BUGSPLAT_DB)") +    endif (BUGSPLAT_DB) +else (USE_BUGSPLAT) +    message(STATUS "Not building with BugSplat") +    if (LINUX) +      add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) +      add_dependencies(viewer linux-crash-logger-strip-target) +    elseif (DARWIN) +      add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) +      add_dependencies(viewer mac-crash-logger) +    elseif (WINDOWS) +      add_subdirectory(${VIEWER_PREFIX}win_crash_logger) +      # add_dependencies(viewer windows-setup windows-crash-logger) +      add_dependencies(viewer windows-crash-logger) +    endif (LINUX) +endif (USE_BUGSPLAT) + +add_subdirectory(${VIEWER_PREFIX}newview) +add_dependencies(viewer secondlife-bin) + +add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL) +  if (LL_TESTS)    # Define after the custom targets are created so    # individual apps can add themselves as dependencies diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index de81512eef..46ddb9d15b 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -66,7 +66,7 @@ if(WINDOWS)      # Filenames are different for 32/64 bit BugSplat file and we don't      # have any control over them so need to branch. -    if (BUGSPLAT_DB) +    if (USE_BUGSPLAT)        if(ADDRESS_SIZE EQUAL 32)          set(release_files ${release_files} BugSplat.dll)          set(release_files ${release_files} BugSplatRc.dll) @@ -76,7 +76,7 @@ if(WINDOWS)          set(release_files ${release_files} BugSplatRc64.dll)          set(release_files ${release_files} BsSndRpt64.exe)        endif(ADDRESS_SIZE EQUAL 32) -    endif (BUGSPLAT_DB) +    endif (USE_BUGSPLAT)      if (FMODSTUDIO)          set(debug_files ${debug_files} fmodL.dll) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 4932e9044f..4937c2a9d7 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -2,6 +2,7 @@  include(00-Common)  include(LLTestCommand)  include(GoogleMock) +include(bugsplat)  include(Tut)  #***************************************************************************** @@ -22,7 +23,6 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)    # there is another branch that will conflict heavily with any changes here.  INCLUDE(GoogleMock) -    IF(LL_TEST_VERBOSE)      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")    ENDIF(LL_TEST_VERBOSE) @@ -87,6 +87,12 @@ INCLUDE(GoogleMock)      IF(LL_TEST_VERBOSE)        MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")      ENDIF(LL_TEST_VERBOSE) + +    if (USE_BUGSPLAT) +      SET_PROPERTY(SOURCE ${${name}_test_SOURCE_FILES} +          APPEND PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +    endif (USE_BUGSPLAT) +      # Headers      GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)      SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES}) @@ -224,6 +230,11 @@ FUNCTION(LL_ADD_INTEGRATION_TEST      SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")    endif(USESYSTEMLIBS) +  if (USE_BUGSPLAT) +      SET_PROPERTY(SOURCE ${source_files} +          APPEND PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +  endif (USE_BUGSPLAT) +    # The following was copied to llcorehttp/CMakeLists.txt's texture_load target.     # Any changes made here should be replicated there.    if (WINDOWS) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index a5770c5528..c81b22e572 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -34,7 +34,6 @@ set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable fo  set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)")  set(ENABLE_MEDIA_PLUGINS ON CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")  set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files") -set(BUGSPLAT_DB "" CACHE STRING "BugSplat database name, if BugSplat crash reporting is desired")  if(LIBS_CLOSED_DIR)    file(TO_CMAKE_PATH "${LIBS_CLOSED_DIR}" LIBS_CLOSED_DIR) diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index 59644b73ce..5f5cc51f63 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -1,25 +1,32 @@ -# BugSplat is engaged by setting BUGSPLAT_DB to the target BugSplat database -# name. -if (BUGSPLAT_DB) -  if (USESYSTEMLIBS) -    message(STATUS "Looking for system BugSplat") -    set(BUGSPLAT_FIND_QUIETLY ON) -    set(BUGSPLAT_FIND_REQUIRED ON) -    include(FindBUGSPLAT) -  else (USESYSTEMLIBS) -    message(STATUS "Engaging autobuild BugSplat") -    include(Prebuilt) -    use_prebuilt_binary(bugsplat) -    if (WINDOWS) -      set(BUGSPLAT_LIBRARIES  -        ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib -        ) -    elseif (DARWIN) -      find_library(BUGSPLAT_LIBRARIES BugsplatMac -        PATHS "${ARCH_PREBUILT_DIRS_RELEASE}") -    else (WINDOWS) +if (INSTALL_PROPRIETARY) +    set(USE_BUGSPLAT ON  CACHE BOOL "Use the BugSplat crash reporting system") +else (INSTALL_PROPRIETARY) +    set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system") +endif (INSTALL_PROPRIETARY) + +if (USE_BUGSPLAT) +    if (NOT USESYSTEMLIBS) +        include(Prebuilt) +        use_prebuilt_binary(bugsplat) +        if (WINDOWS) +            set(BUGSPLAT_LIBRARIES  +                ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib +                ) +        elseif (DARWIN) +            find_library(BUGSPLAT_LIBRARIES BugsplatMac REQUIRED +                NO_DEFAULT_PATH PATHS "${ARCH_PREBUILT_DIRS_RELEASE}") +        else (WINDOWS) +            message(FATAL_ERROR "BugSplat is not supported; add -DUSE_BUGSPLAT=OFF") +        endif (WINDOWS) +    else (NOT USESYSTEMLIBS) +        set(BUGSPLAT_FIND_QUIETLY ON) +        set(BUGSPLAT_FIND_REQUIRED ON) +        include(FindBUGSPLAT) +    endif (NOT USESYSTEMLIBS) + +    set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name") -    endif (WINDOWS)      set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) -  endif (USESYSTEMLIBS) -endif (BUGSPLAT_DB) +    set(BUGSPLAT_DEFINE "LL_BUGSPLAT") +endif (USE_BUGSPLAT) + diff --git a/indra/linux_crash_logger/README.txt b/indra/linux_crash_logger/README.txt new file mode 100644 index 0000000000..6932a8d9c3 --- /dev/null +++ b/indra/linux_crash_logger/README.txt @@ -0,0 +1,3 @@ +This component is no longer used in Linden Lab builds. +Change requests to support continued use by open source +builds are welcome. diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index cecfadcd91..dd266630ea 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -4,6 +4,7 @@ project(llcommon)  include(00-Common)  include(LLCommon) +include(bugsplat)  include(Linking)  include(Boost)  include(LLSharedLibs) @@ -260,10 +261,10 @@ set(llcommon_HEADER_FILES  set_source_files_properties(${llcommon_HEADER_FILES}                              PROPERTIES HEADER_FILE_ONLY TRUE) -if (BUGSPLAT_DB) -  set_source_files_properties(llapp.cpp -    PROPERTIES COMPILE_DEFINITIONS "LL_BUGSPLAT") -endif (BUGSPLAT_DB) +if (USE_BUGSPLAT) +  set_source_files_properties(${llcommon_SOURCE_FILES} +    PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +endif (USE_BUGSPLAT)  list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index a90b294550..6064a843ae 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -528,7 +528,12 @@ void LLApp::setupErrorHandling(bool second_instance)  #endif // LL_LINUX  #endif // ! LL_WINDOWS + +#ifdef LL_BUGSPLAT +    // do not start our own error thread +#else // ! LL_BUGSPLAT  	startErrorThread(); +#endif  }  void LLApp::startErrorThread() @@ -808,7 +813,9 @@ void setup_signals()  	act.sa_flags = SA_SIGINFO;  	// Synchronous signals +#   ifndef LL_BUGSPLAT  	sigaction(SIGABRT, &act, NULL); +#   endif  	sigaction(SIGALRM, &act, NULL);  	sigaction(SIGBUS, &act, NULL);  	sigaction(SIGFPE, &act, NULL); @@ -845,7 +852,9 @@ void clear_signals()  	act.sa_flags = SA_SIGINFO;  	// Synchronous signals +#   ifndef LL_BUGSPLAT  	sigaction(SIGABRT, &act, NULL); +#   endif  	sigaction(SIGALRM, &act, NULL);  	sigaction(SIGBUS, &act, NULL);  	sigaction(SIGFPE, &act, NULL); @@ -898,6 +907,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)  		return;  	case SIGABRT: +        // Note that this handler is not set for SIGABRT when using Bugsplat  		// Abort just results in termination of the app, no funky error handling.  		if (LLApp::sLogInSignal)  		{ 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<std::string, std::string> 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 23419a52a7..111c50af93 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -56,6 +56,10 @@  #include "stringize.h"  #include "llexception.h" +#if LL_WINDOWS +#include <excpt.h> +#endif +  // static  LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller)  { @@ -249,29 +253,58 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl  #if LL_WINDOWS -void LLCoros::winlevel(const callable_t& callable) +static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific + +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 +        return EXCEPTION_CONTINUE_SEARCH; +    } +    else +    { +        // handle it +        return EXCEPTION_EXECUTE_HANDLER; +    } +} + +void LLCoros::winlevel(const std::string& name, const callable_t& callable)  {      __try      { -        callable(); +        toplevelTryWrapper(name, callable);      } -    __except (msc_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); @@ -281,16 +314,12 @@ 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      }      catch (const Stop& exc)      {          LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " -                            << exc.what() << LL_ENDL; +            << exc.what() << LL_ENDL;      }      catch (const LLContinueError&)      { @@ -303,10 +332,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; -    void toplevel(std::string name, callable_t callable); -    struct CoroData;  #if LL_WINDOWS -    static void winlevel(const callable_t& callable); +    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;      static CoroData& get_CoroData(const std::string& caller);      S32 mStackSize; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f876b8ee4a..8355df9045 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -442,8 +442,6 @@ namespace      protected:  		Globals();  	public: -		std::ostringstream messageStream; -		bool messageStreamInUse;  		std::string mFatalMessage;  		void addCallSite(LLError::CallSite&); @@ -453,12 +451,7 @@ namespace  		CallSiteVector callSites;  	}; -	Globals::Globals() -		: messageStream(), -		messageStreamInUse(false), -		callSites() -	{ -	} +	Globals::Globals() {}      Globals* Globals::getInstance()      { @@ -549,7 +542,7 @@ namespace LLError  		mFileLevelMap(),  		mTagLevelMap(),  		mUniqueLogMessages(), -		mCrashFunction(NULL), +		mCrashFunction([](const std::string&){}),  		mTimeFunction(NULL),  		mRecorders(),  		mShouldLogCallCounter(0) @@ -728,7 +721,6 @@ namespace  		LLError::setDefaultLevel(LLError::LEVEL_INFO);  		LLError::setAlwaysFlush(true);  		LLError::setEnabledLogTypesMask(0xFFFFFFFF); -		LLError::setFatalFunction(LLError::crashAndLoop);  		LLError::setTimeFunction(LLError::utcTime);  		// log_to_stderr is only false in the unit and integration tests to keep builds quieter @@ -1360,57 +1352,7 @@ namespace LLError  	} -	std::ostringstream* Log::out() -	{ -		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5); - -		if (lock.isLocked()) -		{ -			Globals* g = Globals::getInstance(); - -			if (!g->messageStreamInUse) -			{ -				g->messageStreamInUse = true; -				return &g->messageStream; -			} -		} - -		return new std::ostringstream; -	} - -	void Log::flush(std::ostringstream* out, char* message) -	{ -		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5); -		if (!lock.isLocked()) -		{ -			return; -		} - -		if(strlen(out->str().c_str()) < 128) -		{ -			strcpy(message, out->str().c_str()); -		} -		else -		{ -			strncpy(message, out->str().c_str(), 127); -			message[127] = '\0' ; -		} - -		Globals* g = Globals::getInstance(); -		if (out == &g->messageStream) -		{ -			g->messageStream.clear(); -			g->messageStream.str(""); -			g->messageStreamInUse = false; -		} -		else -		{ -			delete out; -		} -		return ; -	} - -	void Log::flush(std::ostringstream* out, const CallSite& site) +	void Log::flush(const std::ostringstream& out, const CallSite& site)  	{  		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);  		if (!lock.isLocked()) @@ -1421,22 +1363,11 @@ namespace LLError  		Globals* g = Globals::getInstance();  		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); -		std::string message = out->str(); -		if (out == &g->messageStream) -		{ -			g->messageStream.clear(); -			g->messageStream.str(""); -			g->messageStreamInUse = false; -		} -		else -		{ -			delete out; -		} - +		std::string message = out.str();  		if (site.mPrintOnce)  		{ -            std::ostringstream message_stream; +			std::ostringstream message_stream;  			std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);  			if (messageIter != s->mUniqueLogMessages.end()) @@ -1457,8 +1388,8 @@ namespace LLError  				message_stream << "ONCE: ";  				s->mUniqueLogMessages[message] = 1;  			} -            message_stream << message; -            message = message_stream.str(); +			message_stream << message; +			message = message_stream.str();  		}  		writeToRecorders(site, message); @@ -1466,10 +1397,7 @@ namespace LLError  		if (site.mLevel == LEVEL_ERROR)  		{  			g->mFatalMessage = message; -			if (s->mCrashFunction) -			{ -				s->mCrashFunction(message); -			} +			s->mCrashFunction(message);  		}  	}  } @@ -1533,29 +1461,6 @@ namespace LLError  		return s->mShouldLogCallCounter;  	} -#if LL_WINDOWS -		// VC80 was optimizing the error away. -		#pragma optimize("", off) -#endif -	void crashAndLoop(const std::string& message) -	{ -		// Now, we go kaboom! -		int* make_me_crash = NULL; - -		*make_me_crash = 0; - -		while(true) -		{ -			// Loop forever, in case the crash didn't work? -		} -		 -		// this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever. -		exit(EXIT_FAILURE); -	} -#if LL_WINDOWS -		#pragma optimize("", on) -#endif -  	std::string utcTime()  	{  		time_t now = time(NULL); @@ -1572,33 +1477,7 @@ namespace LLError  namespace LLError  {      -	char** LLCallStacks::sBuffer = NULL ; -	S32    LLCallStacks::sIndex  = 0 ; - -	//static -    void LLCallStacks::allocateStackBuffer() -    { -        if(sBuffer == NULL) -        { -            sBuffer = new char*[512] ; -            sBuffer[0] = new char[512 * 128] ; -            for(S32 i = 1 ; i < 512 ; i++) -            { -                sBuffer[i] = sBuffer[i-1] + 128 ; -            } -            sIndex = 0 ; -        } -    } - -    void LLCallStacks::freeStackBuffer() -    { -        if(sBuffer != NULL) -        { -            delete [] sBuffer[0] ; -            delete [] sBuffer ; -            sBuffer = NULL ; -        } -    } +    LLCallStacks::StringVector LLCallStacks::sBuffer ;      //static      void LLCallStacks::push(const char* function, const int line) @@ -1609,33 +1488,24 @@ namespace LLError              return;          } -        if(sBuffer == NULL) -        { -            allocateStackBuffer(); -        } - -        if(sIndex > 511) +        if(sBuffer.size() > 511)          {              clear() ;          } -        strcpy(sBuffer[sIndex], function) ; -        sprintf(sBuffer[sIndex] + strlen(function), " line: %d ", line) ; -        sIndex++ ; - -        return ; +        std::ostringstream out; +        insert(out, function, line); +        sBuffer.push_back(out.str());      }      //static -    std::ostringstream* LLCallStacks::insert(const char* function, const int line) +    void LLCallStacks::insert(std::ostream& out, const char* function, const int line)      { -        std::ostringstream* _out = LLError::Log::out(); -        *_out << function << " line " << line << " " ; -        return _out ; +        out << function << " line " << line << " " ;      }      //static -    void LLCallStacks::end(std::ostringstream* _out) +    void LLCallStacks::end(const std::ostringstream& out)      {          LLMutexTrylock lock(getMutex<STACKS_MUTEX>(), 5);          if (!lock.isLocked()) @@ -1643,17 +1513,12 @@ namespace LLError              return;          } -        if(sBuffer == NULL) -        { -            allocateStackBuffer(); -        } - -        if(sIndex > 511) +        if(sBuffer.size() > 511)          {              clear() ;          } -        LLError::Log::flush(_out, sBuffer[sIndex++]) ; +        sBuffer.push_back(out.str());      }      //static @@ -1665,33 +1530,30 @@ namespace LLError              return;          } -        if(sIndex > 0) +        if(! sBuffer.empty())          {              LL_INFOS() << " ************* PRINT OUT LL CALL STACKS ************* " << LL_ENDL; -            while(sIndex > 0) +            for (StringVector::const_reverse_iterator ri(sBuffer.rbegin()), re(sBuffer.rend()); +                 ri != re; ++ri)              {                   -                sIndex-- ; -                LL_INFOS() << sBuffer[sIndex] << LL_ENDL; +                LL_INFOS() << (*ri) << LL_ENDL;              }              LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;          } -        if(sBuffer != NULL) -        { -            freeStackBuffer(); -        } +        cleanup();      }      //static      void LLCallStacks::clear()      { -        sIndex = 0 ; +        sBuffer.clear();      }      //static      void LLCallStacks::cleanup()      { -        freeStackBuffer(); +        clear();      }      std::ostream& operator<<(std::ostream& out, const LLStacktrace&) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index ffaa464d77..d439136ca8 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -29,7 +29,9 @@  #define LL_LLERROR_H  #include <sstream> +#include <string>  #include <typeinfo> +#include <vector>  #include "stdtypes.h" @@ -198,9 +200,7 @@ namespace LLError  	{  	public:  		static bool shouldLog(CallSite&); -		static std::ostringstream* out(); -		static void flush(std::ostringstream* out, char* message); -		static void flush(std::ostringstream*, const CallSite&); +		static void flush(const std::ostringstream&, const CallSite&);  		static std::string demangle(const char* mangled);  		/// classname<TYPE>()  		template <typename T> @@ -281,18 +281,15 @@ namespace LLError      class LL_COMMON_API LLCallStacks      {      private: -        static char**  sBuffer ; -        static S32     sIndex ; - -        static void allocateStackBuffer(); -        static void freeStackBuffer(); +        typedef std::vector<std::string> StringVector; +        static StringVector sBuffer ;      public:             static void push(const char* function, const int line) ; -        static std::ostringstream* insert(const char* function, const int line) ; +        static void insert(std::ostream& out, const char* function, const int line) ;          static void print() ;          static void clear() ; -        static void end(std::ostringstream* _out) ; +        static void end(const std::ostringstream& out) ;          static void cleanup();      }; @@ -306,10 +303,11 @@ namespace LLError  //this is cheaper than llcallstacks if no need to output other variables to call stacks.   #define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__) -#define llcallstacks                                                                      \ -	{                                                                                     \ -       std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \ -       (*_out) +#define llcallstacks                                                    \ +	{                                                                   \ +		std::ostringstream _out;                                        \ +		LLError::LLCallStacks::insert(_out, __FUNCTION__, __LINE__) ;   \ +		_out  #define llcallstacksendl                   \  		LLError::End();                    \ @@ -355,11 +353,11 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  		static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \  		lllog_test_() -#define lllog_test_()                                       \ -		if (LL_UNLIKELY(_site.shouldLog()))                 \ -		{                                                   \ -			std::ostringstream* _out = LLError::Log::out(); \ -			(*_out) +#define lllog_test_()                           \ +		if (LL_UNLIKELY(_site.shouldLog()))     \ +		{                                       \ +			std::ostringstream _out;            \ +			_out  #define lllog_site_args_(level, once, tags)                 \  	level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG),    \ @@ -378,15 +376,27 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  //	LL_CONT << " for " << t << " seconds" << LL_ENDL;  //	  //Such computation is done iff the message will be logged. -#define LL_CONT	(*_out) +#define LL_CONT	_out  #define LL_NEWLINE '\n' -#define LL_ENDL                               \ -			LLError::End();                   \ -			LLError::Log::flush(_out, _site); \ -		}                                     \ -	} while(0) +// Use this only in LL_ERRS or in a place that LL_ERRS may not be used +#define LLERROR_CRASH         \ +{                             \ +    int* make_me_crash = NULL;\ +    *make_me_crash = 0;       \ +    exit(*make_me_crash);     \ +} + +#define LL_ENDL                                         \ +            LLError::End();                             \ +            LLError::Log::flush(_out, _site);           \ +            if (_site.mLevel == LLError::LEVEL_ERROR)   \ +            {                                           \ +                LLERROR_CRASH                           \ +            }                                           \ +        }                                               \ +    } while(0)  // NEW Macros for debugging, allow the passing of a string tag diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 25786d5457..e87bb7bf35 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -94,14 +94,16 @@ namespace LLError  	*/  	typedef boost::function<void(const std::string&)> FatalFunction; -	LL_COMMON_API void crashAndLoop(const std::string& message); -		// Default fatal function: access null pointer and loops forever  	LL_COMMON_API void setFatalFunction(const FatalFunction&); -		// The fatal function will be called when an message of LEVEL_ERROR +		// The fatal function will be called after an message of LEVEL_ERROR  		// is logged.  Note: supressing a LEVEL_ERROR message from being logged  		// (by, for example, setting a class level to LEVEL_NONE), will keep -		// the that message from causing the fatal funciton to be invoked. +		// that message from causing the fatal function to be invoked. +		// The passed FatalFunction will be the LAST log function called +		// before LL_ERRS crashes its caller. A FatalFunction can throw an +		// exception, or call exit(), to bypass the crash. It MUST disrupt the +		// flow of control because no caller expects LL_ERRS to return.  	LL_COMMON_API FatalFunction getFatalFunction();  		// Retrieve the previously-set FatalFunction @@ -147,14 +149,14 @@ namespace LLError  		virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;  			// use the level for better display, not for filtering -        virtual bool enabled() { return true; } +		virtual bool enabled() { return true; }  		bool wantsTime();  		bool wantsTags();  		bool wantsLevel();  		bool wantsLocation();   		bool wantsFunctionName(); -        bool wantsMultiline(); +		bool wantsMultiline();  		void showTime(bool show);  		void showTags(bool show); @@ -165,15 +167,35 @@ namespace LLError  	protected:  		bool mWantsTime; -        bool mWantsTags; -        bool mWantsLevel; -        bool mWantsLocation; -        bool mWantsFunctionName; -        bool mWantsMultiline; +		bool mWantsTags; +		bool mWantsLevel; +		bool mWantsLocation; +		bool mWantsFunctionName; +		bool mWantsMultiline;  	};  	typedef boost::shared_ptr<Recorder> RecorderPtr; +    /** +     * Instantiate GenericRecorder with a callable(level, message) to get +     * control on every log message without having to code an explicit +     * Recorder subclass. +     */ +    template <typename CALLABLE> +    class GenericRecorder: public Recorder +    { +    public: +        GenericRecorder(const CALLABLE& callable): +            mCallable(callable) +        {} +        void recordMessage(LLError::ELevel level, const std::string& message) override +        { +            mCallable(level, message); +        } +    private: +        CALLABLE mCallable; +    }; +  	/**  	 * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership  	 * while still ensuring that the allocated memory is eventually freed @@ -181,6 +203,19 @@ namespace LLError  	LL_COMMON_API void addRecorder(RecorderPtr);  	LL_COMMON_API void removeRecorder(RecorderPtr);  		// each error message is passed to each recorder via recordMessage() +	/** +	 * Call addGenericRecorder() with a callable(level, message) to get +	 * control on every log message without having to code an explicit +	 * Recorder subclass. Save the returned RecorderPtr if you later want to +	 * call removeRecorder(). +	 */ +	template <typename CALLABLE> +	RecorderPtr addGenericRecorder(const CALLABLE& callable) +	{ +		RecorderPtr ptr{ new GenericRecorder<CALLABLE>(callable) }; +		addRecorder(ptr); +		return ptr; +	}  	LL_COMMON_API void logToFile(const std::string& filename);  	LL_COMMON_API void logToStderr(); diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index cf8f8cc6a5..e8ea0ab398 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -59,7 +59,6 @@ public:          // pump name -- so it should NOT need tweaking for uniqueness.          mReplyPump(LLUUID::generateNewID().asString()),          mExpect(0), -        mPrevFatalFunction(LLError::getFatalFunction()),          // Instantiate a distinct LLLeapListener for this plugin. (Every          // plugin will want its own collection of managed listeners, etc.)          // Pass it a callback to our connect() method, so it can send events @@ -146,7 +145,9 @@ public:              .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));          // For our lifespan, intercept any LL_ERRS so we can notify plugin -        LLError::setFatalFunction(boost::bind(&LLLeapImpl::fatalFunction, this, _1)); +        mRecorder = LLError::addGenericRecorder( +            [this](LLError::ELevel level, const std::string& message) +            { onError(level, message); });          // Send child a preliminary event reporting our own reply-pump name --          // which would otherwise be pretty tricky to guess! @@ -162,8 +163,7 @@ public:      virtual ~LLLeapImpl()      {          LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL; -        // Restore original FatalFunction -        LLError::setFatalFunction(mPrevFatalFunction); +        LLError::removeRecorder(mRecorder);      }      // Listener for failed launch attempt @@ -377,28 +377,28 @@ public:          return false;      } -    void fatalFunction(const std::string& error) +    void onError(LLError::ELevel level, const std::string& error)      { -        // Notify plugin -        LLSD event; -        event["type"] = "error"; -        event["error"] = error; -        mReplyPump.post(event); - -        // All the above really accomplished was to buffer the serialized -        // event in our WritePipe. Have to pump mainloop a couple times to -        // really write it out there... but time out in case we can't write. -        LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); -        LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); -        LLSD nop; -        F64 until = (LLTimer::getElapsedSeconds() + 2).value(); -        while (childin.size() && LLTimer::getElapsedSeconds() < until) +        if (level == LLError::LEVEL_ERROR)          { -            mainloop.post(nop); +            // Notify plugin +            LLSD event; +            event["type"] = "error"; +            event["error"] = error; +            mReplyPump.post(event); + +            // All the above really accomplished was to buffer the serialized +            // event in our WritePipe. Have to pump mainloop a couple times to +            // really write it out there... but time out in case we can't write. +            LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); +            LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); +            LLSD nop; +            F64 until = (LLTimer::getElapsedSeconds() + 2).value(); +            while (childin.size() && LLTimer::getElapsedSeconds() < until) +            { +                mainloop.post(nop); +            }          } - -        // forward the call to the previous FatalFunction -        mPrevFatalFunction(error);      }  private: @@ -421,7 +421,7 @@ private:          mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;      boost::scoped_ptr<LLEventPump::Blocker> mBlocker;      LLProcess::ReadPipe::size_type mExpect; -    LLError::FatalFunction mPrevFatalFunction; +    LLError::RecorderPtr mRecorder;      boost::scoped_ptr<LLLeapListener> mListener;  }; diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index ad933154c2..6b1986d0e9 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -38,11 +38,6 @@  #include <sstream>  #include <stdexcept> -namespace { -void log(LLError::ELevel level, -         const char* p1, const char* p2, const char* p3, const char* p4); -} // anonymous namespace -  // Our master list of all LLSingletons is itself an LLSingleton. We used to  // store it in a function-local static, but that could get destroyed before  // the last of the LLSingletons -- and ~LLSingletonBase() definitely wants to @@ -218,8 +213,8 @@ void LLSingletonBase::pop_initializing()      if (list.empty())      { -        logerrs("Underflow in stack of currently-initializing LLSingletons at ", -                classname(this).c_str(), "::getInstance()"); +        logerrs({"Underflow in stack of currently-initializing LLSingletons at ", +                classname(this), "::getInstance()"});      }      // Now we know list.back() exists: capture it @@ -240,9 +235,9 @@ void LLSingletonBase::pop_initializing()      // Now validate the newly-popped LLSingleton.      if (back != this)      { -        logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ", -                classname(this).c_str(), "::getInstance() trying to pop ", -                classname(back).c_str()); +        logerrs({"Push/pop mismatch in stack of currently-initializing LLSingletons: ", +                classname(this), "::getInstance() trying to pop ", +                classname(back)});      }      // log AFTER popping so logging singletons don't cry circularity @@ -331,15 +326,15 @@ void LLSingletonBase::capture_dependency()                  //                  // Example: LLNotifications singleton initializes default channels.                  // Channels register themselves with singleton once done. -                logdebugs("LLSingleton circularity: ", out.str().c_str(), -                    classname(this).c_str(), ""); +                logdebugs({"LLSingleton circularity: ", out.str(), +                          classname(this)});              }              else              {                  // Actual circularity with other singleton (or single singleton is used extensively).                  // Dependency can be unclear. -                logwarns("LLSingleton circularity: ", out.str().c_str(), -                    classname(this).c_str(), ""); +                logwarns({"LLSingleton circularity: ", out.str(), +                         classname(this)});              }          }          else @@ -352,8 +347,8 @@ void LLSingletonBase::capture_dependency()              if (current->mDepends.insert(this).second)              {                  // only log the FIRST time we hit this dependency! -                logdebugs(classname(current).c_str(), -                          " depends on ", classname(this).c_str()); +                logdebugs({classname(current), +                          " depends on ", classname(this)});              }          }      } @@ -401,7 +396,7 @@ LLSingletonBase::vec_t LLSingletonBase::dep_sort()  void LLSingletonBase::cleanup_()  { -    logdebugs("calling ", classname(this).c_str(), "::cleanupSingleton()"); +    logdebugs({"calling ", classname(this), "::cleanupSingleton()"});      try      {          cleanupSingleton(); @@ -427,23 +422,23 @@ void LLSingletonBase::deleteAll()              if (! sp->mDeleteSingleton)              {                  // This Should Not Happen... but carry on. -                logwarns(name.c_str(), "::mDeleteSingleton not initialized!"); +                logwarns({name, "::mDeleteSingleton not initialized!"});              }              else              {                  // properly initialized: call it. -                logdebugs("calling ", name.c_str(), "::deleteSingleton()"); +                logdebugs({"calling ", name, "::deleteSingleton()"});                  // From this point on, DO NOT DEREFERENCE sp!                  sp->mDeleteSingleton();              }          }          catch (const std::exception& e)          { -            logwarns("Exception in ", name.c_str(), "::deleteSingleton(): ", e.what()); +            logwarns({"Exception in ", name, "::deleteSingleton(): ", e.what()});          }          catch (...)          { -            logwarns("Unknown exception in ", name.c_str(), "::deleteSingleton()"); +            logwarns({"Unknown exception in ", name, "::deleteSingleton()"});          }      }  } @@ -451,49 +446,40 @@ void LLSingletonBase::deleteAll()  /*---------------------------- Logging helpers -----------------------------*/  namespace { -void log(LLError::ELevel level, -         const char* p1, const char* p2, const char* p3, const char* p4) +std::ostream& operator<<(std::ostream& out, const LLSingletonBase::string_params& args)  { -    LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL; +    // However many args there are in args, stream each of them to 'out'. +    for (auto arg : args) +    { +        out << arg; +    } +    return out;  }  } // anonymous namespace          //static -void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, const char* p4) +void LLSingletonBase::logwarns(const string_params& args)  { -    log(LLError::LEVEL_WARN, p1, p2, p3, p4); +    LL_WARNS("LLSingleton") << args << LL_ENDL;  }  //static -void LLSingletonBase::loginfos(const char* p1, const char* p2, const char* p3, const char* p4) +void LLSingletonBase::loginfos(const string_params& args)  { -    log(LLError::LEVEL_INFO, p1, p2, p3, p4); +    LL_INFOS("LLSingleton") << args << LL_ENDL;  }  //static -void LLSingletonBase::logdebugs(const char* p1, const char* p2, const char* p3, const char* p4) +void LLSingletonBase::logdebugs(const string_params& args)  { -    log(LLError::LEVEL_DEBUG, p1, p2, p3, p4); +    LL_DEBUGS("LLSingleton") << args << LL_ENDL;  }  //static -void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4) +void LLSingletonBase::logerrs(const string_params& args)  { -    log(LLError::LEVEL_ERROR, p1, p2, p3, p4); -    // The other important side effect of LL_ERRS() is -    // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG) -    std::ostringstream out; -    out << p1 << p2 << p3 << p4; -    auto crash = LLError::getFatalFunction(); -    if (crash) -    { -        crash(out.str()); -    } -    else -    { -        LLError::crashAndLoop(out.str()); -    } +    LL_ERRS("LLSingleton") << args << LL_ENDL;  }  std::string LLSingletonBase::demangle(const char* mangled) diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 30a5b21cf8..7c81d65a8b 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -27,9 +27,10 @@  #include <boost/noncopyable.hpp>  #include <boost/unordered_set.hpp> +#include <initializer_list>  #include <list> -#include <vector>  #include <typeinfo> +#include <vector>  #include "mutex.h"  #include "lockstatic.h"  #include "llthread.h"               // on_main_thread() @@ -111,14 +112,13 @@ protected:      void capture_dependency();      // delegate logging calls to llsingleton.cpp -    static void logerrs(const char* p1, const char* p2="", -                        const char* p3="", const char* p4=""); -    static void logwarns(const char* p1, const char* p2="", -                         const char* p3="", const char* p4=""); -    static void loginfos(const char* p1, const char* p2="", -                         const char* p3="", const char* p4=""); -    static void logdebugs(const char* p1, const char* p2="", -                          const char* p3="", const char* p4=""); +public: +    typedef std::initializer_list<const std::string> string_params; +protected: +    static void logerrs  (const string_params&); +    static void logwarns (const string_params&); +    static void loginfos (const string_params&); +    static void logdebugs(const string_params&);      static std::string demangle(const char* mangled);      // these classname() declarations restate template functions declared in      // llerror.h because we avoid #including that here @@ -327,8 +327,8 @@ private:              // init stack to its previous size BEFORE logging so log-machinery              // LLSingletons don't record a dependency on DERIVED_TYPE!              LLSingleton_manage_master<DERIVED_TYPE>().reset_initializing(prev_size); -            logwarns("Error constructing ", classname<DERIVED_TYPE>().c_str(), -                     ": ", err.what()); +            logwarns({"Error constructing ", classname<DERIVED_TYPE>(), +                     ": ", err.what()});              // There isn't a separate EInitState value meaning "we attempted              // to construct this LLSingleton subclass but could not," so use              // DELETED. That seems slightly more appropriate than UNINITIALIZED. @@ -356,8 +356,8 @@ private:              // BEFORE logging, so log-machinery LLSingletons don't record a              // dependency on DERIVED_TYPE!              pop_initializing(lk->mInstance); -            logwarns("Error in ", classname<DERIVED_TYPE>().c_str(), -                     "::initSingleton(): ", err.what()); +            logwarns({"Error in ", classname<DERIVED_TYPE>(), +                     "::initSingleton(): ", err.what()});              // Get rid of the instance entirely. This call depends on our              // recursive_mutex. We could have a deleteSingleton(LockStatic&)              // overload and pass lk, but we don't strictly need it. @@ -506,9 +506,9 @@ public:              case CONSTRUCTING:                  // here if DERIVED_TYPE's constructor (directly or indirectly)                  // calls DERIVED_TYPE::getInstance() -                logerrs("Tried to access singleton ", -                        classname<DERIVED_TYPE>().c_str(), -                        " from singleton constructor!"); +                logerrs({"Tried to access singleton ", +                        classname<DERIVED_TYPE>(), +                        " from singleton constructor!"});                  return nullptr;              case INITIALIZING: @@ -523,9 +523,9 @@ public:              case DELETED:                  // called after deleteSingleton() -                logwarns("Trying to access deleted singleton ", -                         classname<DERIVED_TYPE>().c_str(), -                         " -- creating new instance"); +                logwarns({"Trying to access deleted singleton ", +                         classname<DERIVED_TYPE>(), +                         " -- creating new instance"});                  // fall through              case UNINITIALIZED:              case QUEUED: @@ -552,8 +552,8 @@ public:          } // unlock 'lk'          // Per the comment block above, dispatch to the main thread. -        loginfos(classname<DERIVED_TYPE>().c_str(), -                 "::getInstance() dispatching to main thread"); +        loginfos({classname<DERIVED_TYPE>(), +                 "::getInstance() dispatching to main thread"});          auto instance = LLMainThreadTask::dispatch(              [](){                  // VERY IMPORTANT to call getInstance() on the main thread, @@ -563,16 +563,16 @@ public:                  // the main thread processes them, only the FIRST such request                  // actually constructs the instance -- every subsequent one                  // simply returns the existing instance. -                loginfos(classname<DERIVED_TYPE>().c_str(), -                         "::getInstance() on main thread"); +                loginfos({classname<DERIVED_TYPE>(), +                         "::getInstance() on main thread"});                  return getInstance();              });          // record the dependency chain tracked on THIS thread, not the main          // thread (consider a getInstance() overload with a tag param that          // suppresses dep tracking when dispatched to the main thread)          capture_dependency(instance); -        loginfos(classname<DERIVED_TYPE>().c_str(), -                 "::getInstance() returning on requesting thread"); +        loginfos({classname<DERIVED_TYPE>(), +                 "::getInstance() returning on requesting thread"});          return instance;      } @@ -641,16 +641,16 @@ private:          // For organizational purposes this function shouldn't be called twice          if (lk->mInitState != super::UNINITIALIZED)          { -            super::logerrs("Tried to initialize singleton ", -                           super::template classname<DERIVED_TYPE>().c_str(), -                           " twice!"); +            super::logerrs({"Tried to initialize singleton ", +                           super::template classname<DERIVED_TYPE>(), +                           " twice!"});              return nullptr;          }          else if (on_main_thread())          {              // on the main thread, simply construct instance while holding lock -            super::logdebugs(super::template classname<DERIVED_TYPE>().c_str(), -                             "::initParamSingleton()"); +            super::logdebugs({super::template classname<DERIVED_TYPE>(), +                             "::initParamSingleton()"});              super::constructSingleton(lk, std::forward<Args>(args)...);              return lk->mInstance;          } @@ -662,8 +662,8 @@ private:              lk->mInitState = super::QUEUED;              // very important to unlock here so main thread can actually process              lk.unlock(); -            super::loginfos(super::template classname<DERIVED_TYPE>().c_str(), -                            "::initParamSingleton() dispatching to main thread"); +            super::loginfos({super::template classname<DERIVED_TYPE>(), +                            "::initParamSingleton() dispatching to main thread"});              // Normally it would be the height of folly to reference-bind              // 'args' into a lambda to be executed on some other thread! By              // the time that thread executed the lambda, the references would @@ -674,12 +674,12 @@ private:              // references.              auto instance = LLMainThreadTask::dispatch(                  [&](){ -                    super::loginfos(super::template classname<DERIVED_TYPE>().c_str(), -                                    "::initParamSingleton() on main thread"); +                    super::loginfos({super::template classname<DERIVED_TYPE>(), +                                    "::initParamSingleton() on main thread"});                      return initParamSingleton_(std::forward<Args>(args)...);                  }); -            super::loginfos(super::template classname<DERIVED_TYPE>().c_str(), -                            "::initParamSingleton() returning on requesting thread"); +            super::loginfos({super::template classname<DERIVED_TYPE>(), +                            "::initParamSingleton() returning on requesting thread"});              return instance;          }      } @@ -707,14 +707,14 @@ public:          {          case super::UNINITIALIZED:          case super::QUEUED: -            super::logerrs("Uninitialized param singleton ", -                           super::template classname<DERIVED_TYPE>().c_str()); +            super::logerrs({"Uninitialized param singleton ", +                           super::template classname<DERIVED_TYPE>()});              break;          case super::CONSTRUCTING: -            super::logerrs("Tried to access param singleton ", -                           super::template classname<DERIVED_TYPE>().c_str(), -                           " from singleton constructor!"); +            super::logerrs({"Tried to access param singleton ", +                           super::template classname<DERIVED_TYPE>(), +                           " from singleton constructor!"});              break;          case super::INITIALIZING: @@ -726,8 +726,8 @@ public:              return lk->mInstance;          case super::DELETED: -            super::logerrs("Trying to access deleted param singleton ", -                           super::template classname<DERIVED_TYPE>().c_str()); +            super::logerrs({"Trying to access deleted param singleton ", +                           super::template classname<DERIVED_TYPE>()});              break;          } diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 98905f3b71..6d531d842d 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -354,8 +354,9 @@ void LLThread::setQuitting()      {          mStatus = QUITTING;      } +    // It's only safe to remove mRunCondition if all locked threads were notified +    mRunCondition->broadcast();      mDataLock->unlock(); -    wake();  }  // static diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 9942bc0cf8..22711a83d2 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -276,7 +276,7 @@ std::string LLURI::escapePathAndData(const std::string &str)              std::string fragment;              size_t fragment_pos = str.find('#'); -            if (fragment_pos != std::string::npos) +            if ((fragment_pos != std::string::npos) && (fragment_pos > delim_pos))              {                  query = str.substr(path_size, fragment_pos - path_size);                  fragment = str.substr(fragment_pos); diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 8e1f4c14ac..148c18aabe 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -26,6 +26,7 @@   */  #include <vector> +#include <stdexcept>  #include "linden_common.h" @@ -69,21 +70,41 @@ namespace  namespace  { -	static bool fatalWasCalled; -	void fatalCall(const std::string&) { fatalWasCalled = true; } +	static bool fatalWasCalled = false; +    struct FatalWasCalled: public std::runtime_error +    { +        FatalWasCalled(const std::string& what): std::runtime_error(what) {} +    }; +    void fatalCall(const std::string& msg) { throw FatalWasCalled(msg); }  } +// Because we use LLError::setFatalFunction(fatalCall), any LL_ERRS call we +// issue will throw FatalWasCalled. But we want the test program to continue. +// So instead of writing: +// LL_ERRS("tag") << "some message" << LL_ENDL; +// write: +// CATCH(LL_ERRS("tag"), "some message"); +#define CATCH(logcall, expr)                    \ +    try                                         \ +    {                                           \ +        logcall << expr << LL_ENDL;             \ +    }                                           \ +    catch (const FatalWasCalled&)               \ +    {                                           \ +        fatalWasCalled = true;                  \ +    } +  namespace tut  {  	class TestRecorder : public LLError::Recorder  	{  	public:  		TestRecorder() -            { -                showTime(false); -            } +			{ +				showTime(false); +			}  		virtual ~TestRecorder() -            {} +			{}  		virtual void recordMessage(LLError::ELevel level,  						   const std::string& message) @@ -252,7 +273,7 @@ namespace  		LL_DEBUGS("WriteTag","AnotherTag") << "one" << LL_ENDL;  		LL_INFOS("WriteTag") << "two" << LL_ENDL;  		LL_WARNS("WriteTag") << "three" << LL_ENDL; -		LL_ERRS("WriteTag") << "four" << LL_ENDL; +		CATCH(LL_ERRS("WriteTag"), "four");  	}  }; @@ -380,7 +401,7 @@ namespace  	std::string errorReturningLocation()  	{ -		LL_ERRS() << "die" << LL_ENDL;	int this_line = __LINE__; +		int this_line = __LINE__;	CATCH(LL_ERRS(), "die");  		return locationString(this_line);  	}  } @@ -701,7 +722,7 @@ public:  	static void doDebug()	{ LL_DEBUGS() << "add dice" << LL_ENDL; }  	static void doInfo()	{ LL_INFOS()  << "any idea" << LL_ENDL; }  	static void doWarn()	{ LL_WARNS()  << "aim west" << LL_ENDL; } -	static void doError()	{ LL_ERRS()   << "ate eels" << LL_ENDL; } +	static void doError()	{ CATCH(LL_ERRS(), "ate eels"); }  	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }  }; @@ -712,7 +733,7 @@ public:  	static void doDebug()	{ LL_DEBUGS() << "bed down" << LL_ENDL; }  	static void doInfo()	{ LL_INFOS()  << "buy iron" << LL_ENDL; }  	static void doWarn()	{ LL_WARNS()  << "bad word" << LL_ENDL; } -	static void doError()	{ LL_ERRS()   << "big easy" << LL_ENDL; } +	static void doError()	{ CATCH(LL_ERRS(), "big easy"); }  	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }  }; @@ -874,13 +895,10 @@ namespace tut  namespace  {      std::string writeTagWithSpaceReturningLocation() -	{ -        LL_DEBUGS("Write Tag") << "not allowed" << LL_ENDL;	int this_line = __LINE__; -         -        std::ostringstream location; -        location << LLError::abbreviateFile(__FILE__).c_str() << "(" << this_line << ")"; -        return location.str(); -	} +    { +        int this_line = __LINE__; CATCH(LL_DEBUGS("Write Tag"), "not allowed"); +        return locationString(this_line); +    }  };  namespace tut @@ -894,9 +912,9 @@ namespace tut          std::string location = writeTagWithSpaceReturningLocation();          std::string expected = "Space is not allowed in a log tag at " + location; -		ensure_message_field_equals(0, LEVEL_FIELD, "ERROR"); -		ensure_message_field_equals(0, MSG_FIELD, expected); -		ensure("fatal callback called", fatalWasCalled); +        ensure_message_field_equals(0, LEVEL_FIELD, "ERROR"); +        ensure_message_field_equals(0, MSG_FIELD, expected); +        ensure("fatal callback called", fatalWasCalled);      }  } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index b07d5afbd8..3779fb41bc 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -44,10 +44,6 @@  #include <list>  #include <string> -// statically reference the function in test.cpp... it's short, we could -// replicate, but better to reuse -extern void wouldHaveCrashed(const std::string& message); -  struct WrapLLErrs  {      WrapLLErrs(): @@ -59,7 +55,8 @@ struct WrapLLErrs          mPriorFatal(LLError::getFatalFunction())      {          // Make LL_ERRS call our own operator() method -        LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1)); +        LLError::setFatalFunction( +            [this](const std::string& message){ (*this)(message); });      }      ~WrapLLErrs() @@ -199,11 +196,13 @@ public:          // with that output. If it turns out that saveAndResetSettings() has          // some bad effect, give up and just let the DEBUG level log messages          // display. -		: boost::noncopyable(), +        : boost::noncopyable(), +        mFatalFunction(LLError::getFatalFunction()),          mOldSettings(LLError::saveAndResetSettings()), -		mRecorder(new CaptureLogRecorder()) +        mRecorder(new CaptureLogRecorder())      { -        LLError::setFatalFunction(wouldHaveCrashed); +        // reinstate the FatalFunction we just reset +        LLError::setFatalFunction(mFatalFunction);          LLError::setDefaultLevel(level);          LLError::addRecorder(mRecorder);      } @@ -219,17 +218,18 @@ public:      /// for the sought string.      std::string messageWith(const std::string& search, bool required=true)      { -		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required); +        return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required);      }      std::ostream& streamto(std::ostream& out) const      { -		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out); +        return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out);      }  private: +    LLError::FatalFunction mFatalFunction;      LLError::SettingsStoragePtr mOldSettings; -	LLError::RecorderPtr mRecorder; +    LLError::RecorderPtr mRecorder;  };  #endif /* ! defined(LL_WRAPLLERRS_H) */ diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 240ea2da83..8bb6a657b1 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -13,6 +13,7 @@ include(LLAddBuildTest)  include(LLMessage)  include(LLCommon)  include(Tut) +include(bugsplat)  include_directories (${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/indra/llcorehttp/_httpreplyqueue.cpp b/indra/llcorehttp/_httpreplyqueue.cpp index 2b138f3ad5..229bfdbe07 100644 --- a/indra/llcorehttp/_httpreplyqueue.cpp +++ b/indra/llcorehttp/_httpreplyqueue.cpp @@ -56,7 +56,6 @@ void HttpReplyQueue::addOp(const HttpReplyQueue::opPtr_t &op)  		mQueue.push_back(op);  	} -	mQueueCV.notify_all();  } diff --git a/indra/llcorehttp/_httpreplyqueue.h b/indra/llcorehttp/_httpreplyqueue.h index 928ee10a83..33e205c1c9 100644 --- a/indra/llcorehttp/_httpreplyqueue.h +++ b/indra/llcorehttp/_httpreplyqueue.h @@ -98,7 +98,6 @@ protected:  	OpContainer							mQueue;  	LLCoreInt::HttpMutex				mQueueMutex; -	LLCoreInt::HttpConditionVariable	mQueueCV;  }; // end class HttpReplyQueue diff --git a/indra/llcorehttp/_httprequestqueue.cpp b/indra/llcorehttp/_httprequestqueue.cpp index c6f4ad789f..ad72bdcce6 100644 --- a/indra/llcorehttp/_httprequestqueue.cpp +++ b/indra/llcorehttp/_httprequestqueue.cpp @@ -142,13 +142,19 @@ void HttpRequestQueue::wakeAll()  } -void HttpRequestQueue::stopQueue() +bool HttpRequestQueue::stopQueue()  {  	{  		HttpScopedLock lock(mQueueMutex); -		mQueueStopped = true; -		wakeAll(); +        if (!mQueueStopped) +        { +            mQueueStopped = true; +            wakeAll(); +            return true; +        } +        wakeAll(); +        return false;  	}  } diff --git a/indra/llcorehttp/_httprequestqueue.h b/indra/llcorehttp/_httprequestqueue.h index 3c3d134b07..f0296f30e3 100644 --- a/indra/llcorehttp/_httprequestqueue.h +++ b/indra/llcorehttp/_httprequestqueue.h @@ -124,7 +124,7 @@ public:  	/// them on their way.  	///  	/// Threading:  callable by any thread. -	void stopQueue(); +	bool stopQueue();  protected:  	static HttpRequestQueue *			sInstance; diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 34268d94f6..56f52f1b09 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -87,7 +87,11 @@ HttpService::~HttpService()  		// is a bit tricky.  		if (mRequestQueue)  		{ -			mRequestQueue->stopQueue(); +            if (mRequestQueue->stopQueue()) +            { +                // Give mRequestQueue a chance to finish +                ms_sleep(10); +            }  		}  		if (mThread) diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp index df5aa52fa9..c6365e5091 100644 --- a/indra/llcorehttp/httpoptions.cpp +++ b/indra/llcorehttp/httpoptions.cpp @@ -32,6 +32,7 @@  namespace LLCore  { +    bool HttpOptions::sDefaultVerifyPeer = false;  HttpOptions::HttpOptions() :      mWantHeaders(false), @@ -43,7 +44,7 @@ HttpOptions::HttpOptions() :      mMaxRetryBackoff(HTTP_RETRY_BACKOFF_MAX_DEFAULT),      mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT),      mFollowRedirects(true), -    mVerifyPeer(false), +    mVerifyPeer(sDefaultVerifyPeer),      mVerifyHost(false),      mDNSCacheTimeout(-1L),      mNoBody(false) @@ -122,7 +123,15 @@ void HttpOptions::setHeadersOnly(bool nobody)  {      mNoBody = nobody;      if (mNoBody) +    {          setWantHeaders(true); +        setSSLVerifyPeer(false); +    } +} + +void HttpOptions::setDefaultSSLVerifyPeer(bool verify) +{ +    sDefaultVerifyPeer = verify;  }  }   // end namespace LLCore diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h index 8a6de61b04..41f71896b0 100644 --- a/indra/llcorehttp/httpoptions.h +++ b/indra/llcorehttp/httpoptions.h @@ -143,7 +143,7 @@ public:      /// Instructs the LLCore::HTTPRequest to verify that the exchanged security      /// certificate is authentic.  -    /// Default: false +    /// Default: sDefaultVerifyPeer      void				setSSLVerifyPeer(bool verify);  	bool				getSSLVerifyPeer() const  	{ @@ -177,6 +177,13 @@ public:      {          return mNoBody;      } + +    /// Sets default behavior for verifying that the name in the  +    /// security certificate matches the name of the host contacted. +    /// Defaults false if not set, but should be set according to +    /// viewer's initialization options and command argunments, see +    /// NoVerifySSLCert +    static void         setDefaultSSLVerifyPeer(bool verify);  protected:  	bool				mWantHeaders; @@ -192,6 +199,8 @@ protected:  	bool        		mVerifyHost;  	int					mDNSCacheTimeout;      bool                mNoBody; + +    static bool         sDefaultVerifyPeer;  }; // end class HttpOptions diff --git a/indra/llcrashlogger/README.txt b/indra/llcrashlogger/README.txt new file mode 100644 index 0000000000..6932a8d9c3 --- /dev/null +++ b/indra/llcrashlogger/README.txt @@ -0,0 +1,3 @@ +This component is no longer used in Linden Lab builds. +Change requests to support continued use by open source +builds are welcome. diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 62fcdaf545..e02f3a6306 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -411,6 +411,7 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg      LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);      httpOpts->setTimeout(timeout); +    httpOpts->setSSLVerifyPeer(false);  	for(int i = 0; i < retries; ++i)  	{ diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 293ada7548..28b8e8c06d 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -11,6 +11,7 @@ include(LLKDU)  include(LLImageJ2COJ)  include(ZLIB)  include(LLAddBuildTest) +include(bugsplat)  include(Tut)  include_directories( diff --git a/indra/llinventory/lllandmark.cpp b/indra/llinventory/lllandmark.cpp index 4c6075d6b5..bd7ab3c2c8 100644 --- a/indra/llinventory/lllandmark.cpp +++ b/indra/llinventory/lllandmark.cpp @@ -103,60 +103,104 @@ LLVector3 LLLandmark::getRegionPos() const  // static -LLLandmark* LLLandmark::constructFromString(const char *buffer) +LLLandmark* LLLandmark::constructFromString(const char *buffer, const S32 buffer_size)  { -	const char* cur = buffer;  	S32 chars_read = 0; +	S32 chars_read_total = 0;  	S32 count = 0;  	U32 version = 0; +    bool bad_block = false; +    LLLandmark* result = NULL; +  	// read version  -	count = sscanf( cur, "Landmark version %u\n%n", &version, &chars_read ); -	if(count != 1) -	{ -		goto error; -	} +	count = sscanf( buffer, "Landmark version %u\n%n", &version, &chars_read ); +    chars_read_total += chars_read; -	if(version == 1) -	{ -		LLVector3d pos; -		cur += chars_read; -		// read position -		count = sscanf( cur, "position %lf %lf %lf\n%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read ); -		if( count != 3 ) -		{ -			goto error; -		} -		cur += chars_read; -		// LL_INFOS() << "Landmark read: " << pos << LL_ENDL; -		 -		return new LLLandmark(pos); -	} -	else if(version == 2) -	{ -		// *NOTE: Changing the buffer size will require changing the -		// scanf call below. -		char region_id_str[MAX_STRING];	/* Flawfinder: ignore */ -		LLVector3 pos; -		cur += chars_read; -		count = sscanf(	/* Flawfinder: ignore */ -			cur, -			"region_id %254s\n%n", -			region_id_str, &chars_read); -		if(count != 1) goto error; -		cur += chars_read; -		count = sscanf(cur, "local_pos %f %f %f\n%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read); -		if(count != 3) goto error; -		cur += chars_read; -		LLLandmark* lm = new LLLandmark; -		lm->mRegionID.set(region_id_str); -		lm->mRegionPos = pos; -		return lm; -	} +    if (count != 1 +        || chars_read_total >= buffer_size) +    { +        bad_block = true; +    } + +    if (!bad_block) +    { +        switch (version) +        { +            case 1: +            { +                LLVector3d pos; +                // read position +                count = sscanf(buffer + chars_read_total, "position %lf %lf %lf\n%n", pos.mdV + VX, pos.mdV + VY, pos.mdV + VZ, &chars_read); +                if (count != 3) +                { +                    bad_block = true; +                } +                else +                { +                    LL_DEBUGS("Landmark") << "Landmark read: " << pos << LL_ENDL; +                    result = new LLLandmark(pos); +                } +                break; +            } +            case 2: +            { +                // *NOTE: Changing the buffer size will require changing the +                // scanf call below. +                char region_id_str[MAX_STRING]; +                LLVector3 pos; +                LLUUID region_id; +                count = sscanf( buffer + chars_read_total, +                                "region_id %254s\n%n", +                                region_id_str, +                                &chars_read); +                chars_read_total += chars_read; + +                if (count != 1 +                    || chars_read_total >= buffer_size +                    || !LLUUID::validate(region_id_str)) +                { +                    bad_block = true; +                } + +                if (!bad_block) +                { +                    region_id.set(region_id_str); +                    if (region_id.isNull()) +                    { +                        bad_block = true; +                    } +                } + +                if (!bad_block) +                { +                    count = sscanf(buffer + chars_read_total, "local_pos %f %f %f\n%n", pos.mV + VX, pos.mV + VY, pos.mV + VZ, &chars_read); +                    if (count != 3) +                    { +                        bad_block = true; +                    } +                    else +                    { +                        result = new LLLandmark; +                        result->mRegionID = region_id; +                        result->mRegionPos = pos; +                    } +                } +                break; +            } +            default: +            { +                LL_INFOS("Landmark") << "Encountered Unknown landmark version " << version << LL_ENDL; +                break; +            } +        } +    } - error: -	LL_INFOS() << "Bad Landmark Asset: bad _DATA_ block." << LL_ENDL; -	return NULL; +    if (bad_block) +    { +        LL_INFOS("Landmark") << "Bad Landmark Asset: bad _DATA_ block." << LL_ENDL; +    } +    return result;  } @@ -176,7 +220,7 @@ void LLLandmark::requestRegionHandle(  	if(region_id.isNull())  	{  		// don't bother with checking - it's 0. -		LL_DEBUGS() << "requestRegionHandle: null" << LL_ENDL; +		LL_DEBUGS("Landmark") << "requestRegionHandle: null" << LL_ENDL;  		if(callback)  		{  			const U64 U64_ZERO = 0; @@ -187,7 +231,7 @@ void LLLandmark::requestRegionHandle(  	{  		if(region_id == mLocalRegion.first)  		{ -			LL_DEBUGS() << "requestRegionHandle: local" << LL_ENDL; +			LL_DEBUGS("Landmark") << "requestRegionHandle: local" << LL_ENDL;  			if(callback)  			{  				callback(region_id, mLocalRegion.second); @@ -198,13 +242,13 @@ void LLLandmark::requestRegionHandle(  			region_map_t::iterator it = mRegions.find(region_id);  			if(it == mRegions.end())  			{ -				LL_DEBUGS() << "requestRegionHandle: upstream" << LL_ENDL; +				LL_DEBUGS("Landmark") << "requestRegionHandle: upstream" << LL_ENDL;  				if(callback)  				{  					region_callback_map_t::value_type vt(region_id, callback);  					sRegionCallbackMap.insert(vt);  				} -				LL_DEBUGS() << "Landmark requesting information about: " +				LL_DEBUGS("Landmark") << "Landmark requesting information about: "  						 << region_id << LL_ENDL;  				msg->newMessage("RegionHandleRequest");  				msg->nextBlock("RequestBlock"); @@ -214,7 +258,7 @@ void LLLandmark::requestRegionHandle(  			else if(callback)  			{  				// we have the answer locally - just call the callack. -				LL_DEBUGS() << "requestRegionHandle: ready" << LL_ENDL; +				LL_DEBUGS("Landmark") << "requestRegionHandle: ready" << LL_ENDL;  				callback(region_id, (*it).second.mRegionHandle);  			}  		} diff --git a/indra/llinventory/lllandmark.h b/indra/llinventory/lllandmark.h index 92923ea6fb..be34113a90 100644 --- a/indra/llinventory/lllandmark.h +++ b/indra/llinventory/lllandmark.h @@ -60,7 +60,7 @@ public:  	// constructs a new LLLandmark from a string  	// return NULL if there's an error -	static LLLandmark* constructFromString(const char *buffer); +	static LLLandmark* constructFromString(const char *buffer, const S32 buffer_size);  	// register callbacks that this class handles  	static void registerCallbacks(LLMessageSystem* msg); diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 999bee0a3f..552e820127 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -4,6 +4,7 @@ project(llmath)  include(00-Common)  include(LLCommon) +include(bugsplat)  include(Boost)  include_directories( diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index 4d76dacdf7..be014e7b1e 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -138,13 +138,24 @@ LLCoprocedureManager::~LLCoprocedureManager()      close();  } -LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) +void LLCoprocedureManager::initializePool(const std::string &poolName)  { +    poolMap_t::iterator it = mPoolMap.find(poolName); + +    if (it != mPoolMap.end()) +    { +        // Pools are not supposed to be initialized twice +        // Todo: ideally restrict init to STATE_FIRST +        LL_ERRS() << "Pool is already present " << poolName << LL_ENDL; +        return; +    } +      // Attempt to look up a pool size in the configuration.  If found use that      std::string keyName = "PoolSize" + poolName;      int size = 0;      LL_ERRS_IF(poolName.empty(), "CoprocedureManager") << "Poolname must not be empty" << LL_ENDL; +    LL_INFOS("CoprocedureManager") << "Initializing pool " << poolName << LL_ENDL;      if (mPropertyQueryFn)      { @@ -171,8 +182,6 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::      bool inserted = mPoolMap.emplace(poolName, pool).second;      LL_ERRS_IF(!inserted, "CoprocedureManager") << "Unable to add pool named \"" << poolName << "\" to map. FATAL!" << LL_ENDL; - -    return pool;  }  //------------------------------------------------------------------------- @@ -182,20 +191,28 @@ LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const s      // not exist, create it.      poolMap_t::iterator it = mPoolMap.find(pool); -    poolPtr_t targetPool = (it != mPoolMap.end()) ? it->second : initializePool(pool); +    if (it == mPoolMap.end()) +    { +        // initializing pools in enqueueCoprocedure is not thread safe, +        // at the moment pools need to be initialized manually +        LL_ERRS() << "Uninitialized pool " << pool << LL_ENDL; +    } +    poolPtr_t targetPool = it->second;      return targetPool->enqueueCoprocedure(name, proc);  }  void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn)  {      // functions to discover and store the pool sizes +    // Might be a better idea to make an initializePool(name, size) to init everything externally      mPropertyQueryFn = queryfn;      mPropertyDefineFn = updatefn; -    // workaround until we get mutex into initializePool -    initializePool("AssetStorage");      initializePool("Upload"); +    initializePool("AIS"); // it might be better to have some kind of on-demand initialization for AIS +    // "ExpCache" pool gets initialized in LLExperienceCache +    // asset storage pool gets initialized in LLViewerAssetStorage  }  //------------------------------------------------------------------------- diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h index d5557c129f..2d460826ff 100644 --- a/indra/llmessage/llcoproceduremanager.h +++ b/indra/llmessage/llcoproceduremanager.h @@ -79,6 +79,8 @@ public:      void close();      void close(const std::string &pool); + +    void initializePool(const std::string &poolName);  private: @@ -87,8 +89,6 @@ private:      poolMap_t mPoolMap; -    poolPtr_t initializePool(const std::string &poolName); -      SettingQuery_t mPropertyQueryFn;      SettingUpdate_t mPropertyDefineFn; diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 64c01bd9eb..db22ad2ea3 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -108,6 +108,8 @@ void LLExperienceCache::initSingleton()          cache_stream >> (*this);      } +    LLCoprocedureManager::instance().initializePool("ExpCache"); +      LLCoros::instance().launch("LLExperienceCache::idleCoro",          boost::bind(&LLExperienceCache::idleCoro, this)); diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp index 9db13a37b5..6424117ef3 100644 --- a/indra/llmessage/tests/llcoproceduremanager_test.cpp +++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp @@ -91,6 +91,7 @@ namespace tut      {          Sync sync;          int foo = 0; +        LLCoprocedureManager::instance().initializePool("PoolName");          LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName",              [&foo, &sync] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t & ptr, const LLUUID & id) {                  sync.bump(); diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 7d18bae947..e5b4dec1bd 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -154,9 +154,9 @@ void LLPluginProcessParent::shutdown()      {          EState state = (*it).second->mState;          if (state != STATE_CLEANUP -            || state != STATE_EXITING -            || state != STATE_DONE -            || state != STATE_ERROR) +            && state != STATE_EXITING +            && state != STATE_DONE +            && state != STATE_ERROR)          {              (*it).second->setState(STATE_GOODBYE);          } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index d515fc707a..03b6aac20c 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -50,6 +50,7 @@ U32 LLRender::sUIVerts = 0;  U32 LLTexUnit::sWhiteTexture = 0;  bool LLRender::sGLCoreProfile = false;  bool LLRender::sNsightDebugSupport = false; +LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f);  static const U32 LL_NUM_TEXTURE_LAYERS = 32;   static const U32 LL_NUM_LIGHT_UNITS = 8; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 41f4fe4017..af8568f8a3 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -463,6 +463,7 @@ public:  	static U32 sUIVerts;  	static bool sGLCoreProfile;  	static bool sNsightDebugSupport; +	static LLVector2 sUIGLScaleFactor;  private:  	friend class LLLightState; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 801b945806..dd34f3e383 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -106,11 +106,10 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixe  	top += LLFontGL::sCurOrigin.mY;  	gGL.loadUIIdentity(); -	LLRender2D *r2d_inst = LLRender2D::getInstance(); -	gl_rect_2d(llfloor((F32)left * r2d_inst->mGLScaleFactor.mV[VX]) - pixel_offset, -				llfloor((F32)top * r2d_inst->mGLScaleFactor.mV[VY]) + pixel_offset, -				llfloor((F32)right * r2d_inst->mGLScaleFactor.mV[VX]) + pixel_offset, -				llfloor((F32)bottom * r2d_inst->mGLScaleFactor.mV[VY]) - pixel_offset, +	gl_rect_2d(llfloor((F32)left * LLRender::sUIGLScaleFactor.mV[VX]) - pixel_offset, +				llfloor((F32)top * LLRender::sUIGLScaleFactor.mV[VY]) + pixel_offset, +				llfloor((F32)right * LLRender::sUIGLScaleFactor.mV[VX]) + pixel_offset, +				llfloor((F32)bottom * LLRender::sUIGLScaleFactor.mV[VY]) - pixel_offset,  				filled);  	gGL.popUIMatrix();  } @@ -1568,7 +1567,6 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv  LLRender2D::LLRender2D(LLImageProviderInterface* image_provider)  { -	mGLScaleFactor = LLVector2(1.f, 1.f);  	mImageProvider = image_provider;  	if(mImageProvider)  	{ @@ -1585,7 +1583,7 @@ LLRender2D::~LLRender2D()  	}  } - +// static  void LLRender2D::translate(F32 x, F32 y, F32 z)  {  	gGL.translateUI(x,y,z); @@ -1594,12 +1592,14 @@ void LLRender2D::translate(F32 x, F32 y, F32 z)  	LLFontGL::sCurDepth += z;  } +// static  void LLRender2D::pushMatrix()  {  	gGL.pushUIMatrix();  	LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));  } +// static  void LLRender2D::popMatrix()  {  	gGL.popUIMatrix(); @@ -1608,6 +1608,7 @@ void LLRender2D::popMatrix()  	LLFontGL::sOriginStack.pop_back();  } +// static  void LLRender2D::loadIdentity()  {  	gGL.loadUIIdentity();  @@ -1616,15 +1617,11 @@ void LLRender2D::loadIdentity()  	LLFontGL::sCurDepth = 0.f;  } -void LLRender2D::setScaleFactor(const LLVector2 &scale_factor) -{ -	mGLScaleFactor = scale_factor; -} - +// static  void LLRender2D::setLineWidth(F32 width)  {  	gGL.flush(); -	glLineWidth(width * lerp(mGLScaleFactor.mV[VX], mGLScaleFactor.mV[VY], 0.5f)); +	glLineWidth(width * lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f));  }  LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority) diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 8c01784071..206e68f084 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -128,19 +128,16 @@ class LLRender2D : public LLParamSingleton<LLRender2D>  	LOG_CLASS(LLRender2D);  	~LLRender2D();  public: -	void pushMatrix(); -	void popMatrix(); -	void loadIdentity(); -	void translate(F32 x, F32 y, F32 z = 0.0f); +	static void pushMatrix(); +	static void popMatrix(); +	static void loadIdentity(); +	static void translate(F32 x, F32 y, F32 z = 0.0f); -	void setLineWidth(F32 width); -	void setScaleFactor(const LLVector2& scale_factor); +	static void setLineWidth(F32 width);  	LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);  	LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0); -	LLVector2		mGLScaleFactor; -  protected:  	// since LLRender2D has no control of image provider's lifecycle  	// we need a way to tell LLRender2D that provider died and diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 098621b543..04485c6262 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -1006,7 +1006,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)  		LLRect screen_rect;  		localRectToScreen(child->getRect(),&screen_rect); -		if ( root_rect.overlaps(screen_rect)  && LLUI::getInstance()->mDirtyRect.overlaps(screen_rect)) +		if ( root_rect.overlaps(screen_rect)  && sDirtyRect.overlaps(screen_rect))  		{  			gGL.matrixMode(LLRender::MM_MODELVIEW);  			LLUI::pushMatrix(); diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 7817d99aef..8fc2978bdd 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -180,7 +180,9 @@ void LLConsole::draw()  	LLUIImagePtr imagep = LLUI::getUIImage("transparent"); -	F32 console_opacity = llclamp(LLUI::getInstance()->mSettingGroups["config"]->getF32("ConsoleBackgroundOpacity"), 0.f, 1.f); +	static LLCachedControl<F32> console_bg_opacity(*LLUI::getInstance()->mSettingGroups["config"], "ConsoleBackgroundOpacity", 0.7f); +	F32 console_opacity = llclamp(console_bg_opacity(), 0.f, 1.f); +  	LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");  	color.mV[VALPHA] *= console_opacity; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index e9c980ad9a..cebb521189 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -376,13 +376,15 @@ void LLFloater::layoutDragHandle()  // static  void LLFloater::updateActiveFloaterTransparency()  { -    sActiveControlTransparency = LLUI::getInstance()->mSettingGroups["config"]->getF32("ActiveFloaterTransparency"); +    static LLCachedControl<F32> active_transparency(*LLUI::getInstance()->mSettingGroups["config"], "ActiveFloaterTransparency", 1.f); +    sActiveControlTransparency = active_transparency;  }  // static  void LLFloater::updateInactiveFloaterTransparency()  { -    sInactiveControlTransparency = LLUI::getInstance()->mSettingGroups["config"]->getF32("InactiveFloaterTransparency"); +    static LLCachedControl<F32> inactive_transparency(*LLUI::getInstance()->mSettingGroups["config"], "InactiveFloaterTransparency", 0.95f); +    sInactiveControlTransparency = inactive_transparency;  }  void LLFloater::addResizeCtrls() diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 0c1dcc301b..622c9edba7 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -342,9 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View");  void LLFolderView::filter( LLFolderViewFilter& filter )  {  	LL_RECORD_BLOCK_TIME(FTM_FILTER); -    static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); -    static LLCachedControl<S32> filter_hidden(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); -    filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? filter_visible() : filter_hidden(), 1, 100)); +    static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); +    static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); +    filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100));      // Note: we filter the model, not the view  	getViewModelItem()->filter(filter); @@ -663,7 +663,8 @@ void LLFolderView::draw()  		closeAutoOpenedFolders();  	} -	if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) +	static LLCachedControl<F32> type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f); +	if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size())  	{  		mSearchString.clear();  	} diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 1c6c7b1b35..285bf9f484 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -962,9 +962,10 @@ void LLFolderViewItem::draw()  	//      if (filter_string_length > 0)      { -        F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); +        S32 filter_offset = mViewModelItem->getFilterStringOffset(); +        F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length);          F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; -        font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, +        font->renderUTF8( combined_string, filter_offset, match_string_left, yy,              sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,              filter_string_length, S32_MAX, &right_x, FALSE );      } @@ -1607,7 +1608,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(); @@ -1630,7 +1631,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 da09d139e9..616d2e7d86 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -387,7 +387,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/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index ea106b5fae..93122503d1 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,9 +48,9 @@ std::string LLFolderViewModelCommon::getStatusText()  void LLFolderViewModelCommon::filter()  { -    static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); -    getFilter().resetTime(llclamp(filter_visible(), 1, 100)); -	mFolderView->getViewModelItem()->filter(getFilter()); +    static LLCachedControl<S32> max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); +    getFilter().resetTime(llclamp(max_time(), 1, 100)); +    mFolderView->getViewModelItem()->filter(getFilter());  }  bool LLFolderViewModelItemCommon::hasFilterStringMatch() diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index acfe4a0cba..f89064d59a 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -136,6 +136,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)  		}  	} +    mRoundedSquareImgp = LLUI::getUIImage("Rounded_Square");  	if (p.thumb_image.isProvided())  	{  		mThumbImagep = LLUI::getUIImage(p.thumb_image()); @@ -666,8 +667,6 @@ void LLMultiSlider::draw()  	F32 opacity = getEnabled() ? 1.f : 0.3f;  	// Track -	LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square"); -  	static LLUICachedControl<S32> multi_track_height_width ("UIMultiTrackHeight", 0);  	S32 height_offset = 0;  	S32 width_offset = 0; @@ -685,7 +684,7 @@ void LLMultiSlider::draw()  	if(mDrawTrack)  	{  		track_rect.stretch(-1); -		thumb_imagep->draw(track_rect, mTrackColor.get() % opacity); +		mRoundedSquareImgp->draw(track_rect, mTrackColor.get() % opacity);  	}  	// if we're supposed to use a drawn triangle @@ -704,7 +703,7 @@ void LLMultiSlider::draw()  				mTriangleColor.get() % opacity, TRUE);  		}  	} -	else if (!thumb_imagep && !mThumbImagep) +	else if (!mRoundedSquareImgp && !mThumbImagep)  	{  		// draw all the thumbs  		curSldrIt = mThumbRects.end(); @@ -757,7 +756,7 @@ void LLMultiSlider::draw()  			}  			else  			{ -				thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); +                mRoundedSquareImgp->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);  			}  		} @@ -772,7 +771,7 @@ void LLMultiSlider::draw()  				}  				else  				{ -					thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); +                    mRoundedSquareImgp->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());  				}  			}  		} @@ -784,7 +783,7 @@ void LLMultiSlider::draw()              }              else              { -                thumb_imagep->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); +                mRoundedSquareImgp->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());              }          } @@ -822,11 +821,11 @@ void LLMultiSlider::draw()  			}  			else if (capture == this)  			{ -				thumb_imagep->drawSolid(mIt->second, curThumbColor); +                mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor);  			}  			else  			{ -				thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity); +                mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor % opacity);  			}  		} @@ -846,11 +845,11 @@ void LLMultiSlider::draw()  			}  			else if (capture == this)  			{ -				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get()); +                mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());  			}  			else  			{ -				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity); +                mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);  			}  		}  		if(hoverSldrIt != mThumbRects.end())  @@ -861,7 +860,7 @@ void LLMultiSlider::draw()  			}  			else  			{ -				thumb_imagep->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get()); +                mRoundedSquareImgp->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get());  			}  		}  	} diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index 99a78d6e09..3cb4b760b0 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -150,6 +150,7 @@ protected:  	LLUIColor		mDisabledThumbColor;  	LLUIColor		mTriangleColor;  	LLUIImagePtr	mThumbImagep; //blimps on the slider, for now no 'disabled' support +    LLUIImagePtr	mRoundedSquareImgp; //blimps on the slider, for now no 'disabled' support  	const EOrientation	mOrientation; diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h index acc047527f..580f353c7d 100644 --- a/indra/llui/llnotificationptr.h +++ b/indra/llui/llnotificationptr.h @@ -27,9 +27,8 @@  // Many classes just store a single LLNotificationPtr  // and llnotifications.h is very large, so define this ligher header. -#include <boost/shared_ptr.hpp>  class LLNotification; -typedef boost::shared_ptr<LLNotification> LLNotificationPtr; +typedef std::shared_ptr<LLNotification> LLNotificationPtr;  #endif diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 2f4578da17..39576ad86d 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -85,7 +85,6 @@  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp>  #include <boost/type_traits.hpp>  #include <boost/signals2.hpp>  #include <boost/range.hpp> @@ -304,7 +303,7 @@ typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibility   */  class LLNotification  :   	boost::noncopyable, -	public boost::enable_shared_from_this<LLNotification> +	public std::enable_shared_from_this<LLNotification>  {  LOG_CLASS(LLNotification);  friend class LLNotifications; @@ -743,7 +742,10 @@ public:  	:	mFilter(filter),   		mItems()   	{} -	virtual ~LLNotificationChannelBase() {} +    virtual ~LLNotificationChannelBase() +    { +        mItems.clear(); +    }  	// you can also connect to a Channel, so you can be notified of  	// changes to this channel      LLBoundListener connectChanged(const LLEventListener& slot) @@ -873,6 +875,7 @@ class LLNotifications :  {  	LLSINGLETON(LLNotifications);  	LOG_CLASS(LLNotifications); +	virtual ~LLNotifications() {}  public: @@ -1070,7 +1073,11 @@ public:  	LLPersistentNotificationChannel()   		:	LLNotificationChannel("Persistent", "Visible", ¬ificationFilter)  	{} -	virtual ~LLPersistentNotificationChannel() {} + +    virtual ~LLPersistentNotificationChannel() +    { +        mHistory.clear(); +    }  	typedef std::vector<LLNotificationPtr> history_list_t;  	history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index cc9ff7a487..82b0415624 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -257,7 +257,7 @@ void LLScrollColumnHeader::updateResizeBars()  	for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)  	{  		LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); -		if (columnp->mHeader && columnp->mHeader->canResize()) +		if (columnp && columnp->mHeader && columnp->mHeader->canResize())  		{  			num_resizable_columns++;  		} @@ -269,7 +269,7 @@ void LLScrollColumnHeader::updateResizeBars()  	for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)  	{  		LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); -		if (!columnp->mHeader) continue; +		if (!columnp || !columnp->mHeader) continue;  		BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();  		columnp->mHeader->enableResizeBar(enable);  		if (enable) diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index be85f1cb6a..de644185fd 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -743,12 +743,12 @@ void LLScrollListCtrl::updateColumns(bool force_update)  	LLScrollColumnHeader* last_header = NULL;  	for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it)  	{ -		if ((*column_ordered_it)->getWidth() < 0) +		LLScrollListColumn* column = *column_ordered_it; +		if (!column || column->getWidth() < 0)  		{  			// skip hidden columns  			continue;  		} -		LLScrollListColumn* column = *column_ordered_it;  		if (column->mHeader)  		{ diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index e6f466ec78..0961db37ba 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -1125,7 +1125,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)  	BOOL handled = FALSE;  	S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY); -	S32 drag_threshold = LLUI::getInstance()->mSettingGroups["config"]->getS32("DragAndDropDistanceThreshold"); +	static LLCachedControl<S32> drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3);  	if (mouse_distance_squared > drag_threshold * drag_threshold  		&& hasMouseCapture() &&   		mStartDragItemCallback && mHandleDragItemCallback) diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 422534b781..2f56a8b1d0 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -358,8 +358,8 @@ void LLToolTip::draw()  	if (mFadeTimer.getStarted())  	{ -		F32 tool_tip_fade_time = LLUI::getInstance()->mSettingGroups["config"]->getF32("ToolTipFadeTime"); -		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f); +		static LLCachedControl<F32> tool_tip_fade_time(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFadeTime", 0.2f); +		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time(), 1.f, 0.f);  		if (alpha == 0.f)  		{  			// finished fading out, so hide ourselves diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 656b69d3ed..6f16745bd3 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -154,7 +154,6 @@ mAudioCallback(audio_callback),  mDeferredAudioCallback(deferred_audio_callback),  mWindow(NULL), // set later in startup  mRootView(NULL), -mDirty(FALSE),  mHelpImpl(NULL)  {  	LLRender2D::initParamSingleton(image_provider); @@ -203,19 +202,6 @@ void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& rem  	mClearPopupsFunc = clear_popups;  } -void LLUI::dirtyRect(LLRect rect) -{ -	if (!mDirty) -	{ -		mDirtyRect = rect; -		mDirty = TRUE; -	} -	else -	{ -		mDirtyRect.unionWith(rect); -	} -} -  void LLUI::setMousePositionScreen(S32 x, S32 y)  {  #if defined(LL_DARWIN) @@ -510,6 +496,18 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)  	return context;  } +//static +LLVector2& LLUI::getScaleFactor() +{ +    return LLRender::sUIGLScaleFactor; +} + +//static +void LLUI::setScaleFactor(const LLVector2& scale_factor) +{ +    LLRender::sUIGLScaleFactor = scale_factor; +} +  // LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 9856e551cc..30dbd7248f 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -245,10 +245,6 @@ public:  	void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& ); -	LLRect	mDirtyRect; -	BOOL		mDirty; -	void		dirtyRect(LLRect rect); -  	// Return the ISO639 language name ("en", "ko", etc.) for the viewer UI.  	// http://www.loc.gov/standards/iso639-2/php/code_list.php  	std::string getUILanguage(); @@ -313,14 +309,14 @@ public:  	void positionViewNearMouse(LLView* view,	S32 spawn_x = S32_MAX, S32 spawn_y = S32_MAX);  	// LLRender2D wrappers -	static void pushMatrix() { LLRender2D::getInstance()->pushMatrix(); } -	static void popMatrix() { LLRender2D::getInstance()->popMatrix(); } -	static void loadIdentity() { LLRender2D::getInstance()->loadIdentity(); } -	static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::getInstance()->translate(x, y, z); } - -	static LLVector2& getScaleFactor() { return LLRender2D::getInstance()->mGLScaleFactor; } -	static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::getInstance()->setScaleFactor(scale_factor); } -	static void setLineWidth(F32 width) { LLRender2D::getInstance()->setLineWidth(width); } +	static void pushMatrix() { LLRender2D::pushMatrix(); } +	static void popMatrix() { LLRender2D::popMatrix(); } +	static void loadIdentity() { LLRender2D::loadIdentity(); } +	static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); } + +    static LLVector2& getScaleFactor(); +    static void setScaleFactor(const LLVector2& scale_factor); +	static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); }  	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0)  		{ return LLRender2D::getInstance()->getUIImageByID(image_id, priority); }  	static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0) diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 20dda54771..e43c52c0c2 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -176,7 +176,7 @@ void LLUrlEntryBase::callObservers(const std::string &id,  bool LLUrlEntryBase::isLinkDisabled() const  {  	// this allows us to have a global setting to turn off text hyperlink highlighting/action -	bool globally_disabled = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("DisableTextHyperlinkActions"); +	static LLCachedControl<bool> globally_disabled(*LLUI::getInstance()->mSettingGroups["config"], "DisableTextHyperlinkActions", false);  	return globally_disabled;  } @@ -464,7 +464,9 @@ LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()  							"|"  							"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)"  							"|" -							"(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))" +							"(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?)" +							"|" +							"(https?://([-\\w\\.]*\\.)?secondlife\\.io(:\\d{1,5})?))"  							"\\/\\S*",  		boost::regex::perl|boost::regex::icase); @@ -1127,7 +1129,7 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const  //  LLUrlEntryRegion::LLUrlEntryRegion()  { -	mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?", +	mPattern = boost::regex("secondlife:///app/region/[A-Za-z0-9()_%]+(/\\d+)?(/\\d+)?(/\\d+)?/?",  							boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_slurl.xml";  	mTooltip = LLTrans::getString("TooltipSLURL"); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index cd47e2ecea..b942be2a4a 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -60,6 +60,8 @@ static const S32 LINE_HEIGHT = 15;  S32		LLView::sDepth = 0;  bool	LLView::sDebugRects = false; +bool	LLView::sIsRectDirty = false; +LLRect	LLView::sDirtyRect;  bool	LLView::sDebugRectsShowNames = true;  bool	LLView::sDebugKeys = false;  bool	LLView::sDebugMouseHandling = false; @@ -885,14 +887,16 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)  	std::string tooltip = getToolTip();  	if (!tooltip.empty())  	{ +        static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f); +        static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f); +        static LLCachedControl<bool> allow_ui_tooltips(*LLUI::getInstance()->mSettingGroups["config"], "BasicUITooltips", true);  		// allow "scrubbing" over ui by showing next tooltip immediately  		// if previous one was still visible  		F32 timeout = LLToolTipMgr::instance().toolTipVisible()  -		              ? LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipFastDelay" ) -		              : LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipDelay" ); +		              ? tooltip_fast_delay +		              : tooltip_delay;  		// Even if we don't show tooltips, consume the event, nothing below should show tooltip -		bool allow_ui_tooltips = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("BasicUITooltips");  		if (allow_ui_tooltips)  		{  			LLToolTipMgr::instance().show(LLToolTip::Params() @@ -1189,7 +1193,7 @@ void LLView::drawChildren()  			if (viewp->getVisible() && viewp->getRect().isValid())  			{  				LLRect screen_rect = viewp->calcScreenRect(); -				if ( rootp->getLocalRect().overlaps(screen_rect)  && LLUI::getInstance()->mDirtyRect.overlaps(screen_rect)) +				if ( rootp->getLocalRect().overlaps(screen_rect)  && sDirtyRect.overlaps(screen_rect))  				{  					LLUI::pushMatrix();  					{ @@ -1231,7 +1235,15 @@ void LLView::dirtyRect()  		parent = parent->getParent();  	} -	LLUI::getInstance()->dirtyRect(cur->calcScreenRect()); +    if (!sIsRectDirty) +    { +        sDirtyRect = cur->calcScreenRect(); +        sIsRectDirty = true; +    } +    else +    { +        sDirtyRect.unionWith(cur->calcScreenRect()); +    }  }  //Draw a box for debugging. diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 5c91c37d3c..c60dcf3344 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -657,6 +657,9 @@ public:  	// Draw debug rectangles around widgets to help with alignment and spacing  	static bool	sDebugRects; +    static bool sIsRectDirty; +    static LLRect sDirtyRect; +  	// Draw widget names and sizes when drawing debug rectangles, turning this  	// off is useful to make the rectangles themselves easier to see.  	static bool sDebugRectsShowNames; diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 4a4fdb72e3..1a474cca90 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -739,11 +739,6 @@ namespace tut  				  "XXX secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30 XXX",  				  "secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30"); -		// DEV-35459: SLURLs and teleport Links not parsed properly -		testRegex("Region with quote", url, -				  "XXX secondlife:///app/region/A'ksha%20Oasis/41/166/701 XXX", -			          "secondlife:///app/region/A%27ksha%20Oasis/41/166/701"); -  		// Rendering tests.  		testLabel("Render /app/region/Ahern/50/50/50/", url,  			"secondlife:///app/region/Ahern/50/50/50/", diff --git a/indra/mac_crash_logger/README.txt b/indra/mac_crash_logger/README.txt new file mode 100644 index 0000000000..6932a8d9c3 --- /dev/null +++ b/indra/mac_crash_logger/README.txt @@ -0,0 +1,3 @@ +This component is no longer used in Linden Lab builds. +Change requests to support continued use by open source +builds are welcome. diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fc8d8b805b..8e6c797c75 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -8,9 +8,7 @@ include(00-Common)  include(Linking)  include(Boost) -if (BUGSPLAT_DB) -  include(bugsplat) -endif (BUGSPLAT_DB) +include(bugsplat)  include(BuildPackagesInfo)  include(BuildVersion)  include(CMakeCopyIfDifferent) @@ -96,18 +94,18 @@ include_directories(      ${CMAKE_CURRENT_SOURCE_DIR}      ) -if (BUGSPLAT_DB) -  include_directories( -    ${BUGSPLAT_INCLUDE_DIR} -    ) -endif (BUGSPLAT_DB) -  include_directories(SYSTEM      ${LLCOMMON_SYSTEM_INCLUDE_DIRS}      ${LLXML_SYSTEM_INCLUDE_DIRS}      ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS}      ) +if (USE_BUGSPLAT) +  include_directories(AFTER +    ${BUGSPLAT_INCLUDE_DIR} +    ) +endif (USE_BUGSPLAT) +  set(viewer_SOURCE_FILES      groupchatlistener.cpp      llaccountingcostmanager.cpp @@ -1415,11 +1413,11 @@ if (DARWIN)      ${COREAUDIO_LIBRARY}      ) -  if (BUGSPLAT_DB) +  if (USE_BUGSPLAT)      list(APPEND viewer_LIBRARIES        ${BUGSPLAT_LIBRARIES}        ) -  endif (BUGSPLAT_DB) +  endif (USE_BUGSPLAT)    # Add resource files to the project.    set(viewer_RESOURCE_FILES @@ -1757,10 +1755,10 @@ if (SDL_FOUND)      )  endif (SDL_FOUND) -if (BUGSPLAT_DB) +if (USE_BUGSPLAT)    set_property(TARGET ${VIEWER_BINARY_NAME} -    PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") -endif (BUGSPLAT_DB) +    PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +endif (USE_BUGSPLAT)  # add package files  file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST @@ -1839,9 +1837,12 @@ if (WINDOWS)        media_plugin_libvlc        media_plugin_example        winmm_shim -      windows-crash-logger        ) +    if (NOT USE_BUGSPLAT) +        LIST(APPEND COPY_INPUT_DEPENDENCIES windows-crash-logger) +    endif (NOT USE_BUGSPLAT) +      if (ADDRESS_SIZE EQUAL 64)          list(APPEND COPY_INPUT_DEPENDENCIES              ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk_x64.dll @@ -1904,10 +1905,11 @@ if (WINDOWS)        add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)      endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) -    add_dependencies(${VIEWER_BINARY_NAME} -      SLPlugin -      windows-crash-logger -    ) +    add_dependencies(${VIEWER_BINARY_NAME} SLPlugin) + +    if (NOT USE_BUGSPLAT) +        add_dependencies(${VIEWER_BINARY_NAME} windows-crash-logger) +    endif (NOT USE_BUGSPLAT)      # sets the 'working directory' for debugging from visual studio.      # Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865) @@ -2059,11 +2061,11 @@ target_link_libraries(${VIEWER_BINARY_NAME}      ${LLAPPEARANCE_LIBRARIES}      ) -if (BUGSPLAT_DB) +if (USE_BUGSPLAT)    target_link_libraries(${VIEWER_BINARY_NAME}      ${BUGSPLAT_LIBRARIES}      ) -endif (BUGSPLAT_DB) +endif (USE_BUGSPLAT)  set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH      "Path to artwork files.") @@ -2074,13 +2076,16 @@ if (LINUX)    # These are the generated targets that are copied to package/    set(COPY_INPUT_DEPENDENCIES      ${VIEWER_BINARY_NAME} -    linux-crash-logger      SLPlugin      media_plugin_gstreamer010      media_plugin_libvlc      llcommon      ) +  if (NOT USE_BUGSPLAT) +      LIST(APPEND COPY_INPUT_DEPENDENCIES linux-crash-logger) +  endif (NOT USE_BUGSPLAT) +    add_custom_command(        OUTPUT ${product}.tar.bz2        COMMAND ${PYTHON_EXECUTABLE} @@ -2211,8 +2216,11 @@ if (DARWIN)        ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py      ) -  add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef mac-crash-logger) -  add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger) +  add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef) + +  if (NOT USE_BUGSPLAT) +      add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger) +  endif (NOT USE_BUGSPLAT)    if (ENABLE_SIGNING)        set(SIGNING_SETTING "--signature=${SIGNING_IDENTITY}") @@ -2255,7 +2263,7 @@ endif (INSTALL)  # Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh  if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE) -  if (NOT BUGSPLAT_DB) +  if (NOT USE_BUGSPLAT)      # Breakpad symbol-file generation      set(SYMBOL_SEARCH_DIRS "")      if (WINDOWS) @@ -2272,7 +2280,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE        list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")        list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")        list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}") -      set(VIEWER_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger") +      set(VIEWER_EXE_GLOBS "'${product}' SLPlugin")        set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger")        set(VIEWER_LIB_GLOB "*.dylib")      endif (DARWIN) @@ -2310,7 +2318,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE        add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}")      endif (WINDOWS OR LINUX) -  else (NOT BUGSPLAT_DB) +  else (NOT USE_BUGSPLAT)      # BugSplat symbol-file generation      if (WINDOWS)        # Just pack up a tarball containing only the .pdb file for the @@ -2394,9 +2402,9 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE      if (LINUX)        # TBD      endif (LINUX) -  endif (NOT BUGSPLAT_DB) +  endif (NOT USE_BUGSPLAT) -  # for both BUGSPLAT_DB and Breakpad +  # for both Bugsplat and Breakpad    add_dependencies(llpackage generate_symbols)  endif () @@ -2529,6 +2537,10 @@ if (LL_TESTS)      ${BOOST_CONTEXT_LIBRARY}    ) +  LL_ADD_INTEGRATION_TEST(cppfeatures +    "" +    "${test_libs}" +    )    LL_ADD_INTEGRATION_TEST(llsechandler_basic      llsechandler_basic.cpp      "${test_libs}" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6de3fd04e6..28fc63b62e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14324,19 +14324,6 @@        <key>Value</key>        <integer>1</integer>      </map> -    <!-- SL-12594 removes fixed function rendering -    <key>VertexShaderEnable</key> -    <map> -      <key>Comment</key> -      <string>Enable/disable all GLSL shaders (debug)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>0</integer> -    </map> -    <-->      <key>VivoxAutoPostCrashDumps</key>      <map>        <key>Comment</key> @@ -14425,7 +14412,52 @@        <key>Value</key>        <integer>44125</integer>      </map> -    <key>VoiceCallsFriendsOnly</key> + +  <key>VivoxVadAuto</key> +  <map> +    <key>Comment</key> +    <string>A flag indicating if the automatic VAD is enabled (1) or disabled (0). The individual settings are ignored if the auto-mode is enabled</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>VivoxVadHangover</key> +  <map> +    <key>Comment</key> +    <string>The time (in milliseconds) that it takes or the VAD to switch back to silence from speech mode after the last speech frame has been detected</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>2000</integer> +  </map> +  <key>VivoxVadNoiseFloor</key> +  <map> +    <key>Comment</key> +    <string>A dimensionless value between 0 and 20000 (default 576) that controls the maximum level at which the noise floor may be set at by the VAD's noise tracking</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>576</integer> +  </map> +  <key>VivoxVadSensitivity</key> +  <map> +    <key>Comment</key> +    <string>A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>VoiceCallsFriendsOnly</key>      <map>        <key>Comment</key>        <string>(Deprecated) Only accept voice calls from residents on your friends list</string> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index e6ee458719..f1bf8d76c2 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -56,7 +56,6 @@ RenderVBOMappingDisable		1	1  RenderVolumeLODFactor		1	2.0  UseStartScreen				1	1  UseOcclusion				1	1 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  Disregard128DefaultDrawDistance	1	1 @@ -95,7 +94,6 @@ RenderTerrainLODFactor		1	1  RenderTransparentWater		1	0  RenderTreeLODFactor			1	0  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	0  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -127,7 +125,6 @@ RenderTerrainLODFactor		1	1  RenderTransparentWater		1	0  RenderTreeLODFactor			1	0  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -158,7 +155,6 @@ RenderTerrainLODFactor		1	1.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -189,7 +185,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -220,7 +215,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	0 @@ -251,7 +245,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	1 @@ -282,7 +275,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	1 @@ -312,7 +304,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	1.0  RenderVolumeLODFactor		1	2.0 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  RenderDeferred				1	1 @@ -380,7 +371,6 @@ list NoPixelShaders  RenderAvatarVP				0	0  RenderAvatarCloth			0	0  RenderReflectionDetail		0	0 -VertexShaderEnable			0	0  WindLightUseAtmosShaders	0	0  RenderDeferred				0	0  RenderDeferredSSAO			0	0 @@ -394,7 +384,6 @@ list NoVertexShaders  RenderAvatarVP				0	0  RenderAvatarCloth			0	0  RenderReflectionDetail		0	0 -VertexShaderEnable			0	0  WindLightUseAtmosShaders	0	0  RenderDeferred				0	0  RenderDeferredSSAO			0	0 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index bc836a99ca..5542eee6ca 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -56,7 +56,6 @@ RenderVBOMappingDisable		1	1  RenderVolumeLODFactor		1	2.0  UseStartScreen				1	1  UseOcclusion				1	1 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  Disregard128DefaultDrawDistance	1	1 @@ -94,7 +93,6 @@ RenderTerrainLODFactor		1	1  RenderTransparentWater		1	0  RenderTreeLODFactor			1	0  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -126,7 +124,6 @@ RenderTerrainLODFactor		1	1  RenderTransparentWater		1	0  RenderTreeLODFactor			1	0  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	0  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -157,7 +154,6 @@ RenderTerrainLODFactor		1	1.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -188,7 +184,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -219,7 +214,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderUseAdvancedAtmospherics 1 0 @@ -250,7 +244,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	1 @@ -281,7 +274,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	1 @@ -311,7 +303,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	1.0  RenderVolumeLODFactor		1	2.0 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  RenderDeferred				1	1 @@ -379,7 +370,6 @@ list NoPixelShaders  RenderAvatarVP				0	0  RenderAvatarCloth			0	0  RenderReflectionDetail		0	0 -VertexShaderEnable			0	0  WindLightUseAtmosShaders	0	0  RenderDeferred				0	0  RenderDeferredSSAO			0	0 @@ -393,7 +383,6 @@ list NoVertexShaders  RenderAvatarVP				0	0  RenderAvatarCloth			0	0  RenderReflectionDetail		0	0 -VertexShaderEnable			0	0  WindLightUseAtmosShaders	0	0  RenderDeferred				0	0  RenderDeferredSSAO			0	0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 68202a571f..bac6fd5708 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -56,7 +56,6 @@ RenderVBOMappingDisable		1	1  RenderVolumeLODFactor		1	2.0  UseStartScreen				1	1  UseOcclusion				1	1 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  Disregard128DefaultDrawDistance	1	1 @@ -95,7 +94,6 @@ RenderTerrainLODFactor		1	1  RenderTransparentWater		1	0  RenderTreeLODFactor			1	0  RenderVolumeLODFactor		1	0.5 -VertexShaderEnable			1	0  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -127,7 +125,6 @@ RenderTerrainLODFactor		1	1  RenderTransparentWater		1	0  RenderTreeLODFactor			1	0  RenderVolumeLODFactor		1	0.5 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -158,7 +155,6 @@ RenderTerrainLODFactor		1	1.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	0  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -189,7 +185,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	0  RenderDeferredSSAO			1	0 @@ -220,7 +215,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	0 @@ -251,7 +245,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	1 @@ -282,7 +275,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	0.5  RenderVolumeLODFactor		1	1.125 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  RenderDeferred				1	1  RenderDeferredSSAO			1	1 @@ -312,7 +304,6 @@ RenderTerrainLODFactor		1	2.0  RenderTransparentWater		1	1  RenderTreeLODFactor			1	1.0  RenderVolumeLODFactor		1	2.0 -VertexShaderEnable			1	1  WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  RenderDeferred				1	1 @@ -374,7 +365,6 @@ list NoPixelShaders  RenderAvatarVP				0	0  RenderAvatarCloth			0	0  RenderReflectionDetail		0	0 -VertexShaderEnable			0	0  WindLightUseAtmosShaders	0	0  RenderDeferred				0	0  RenderDeferredSSAO			0	0 @@ -388,7 +378,6 @@ list NoVertexShaders  RenderAvatarVP				0	0  RenderAvatarCloth			0	0  RenderReflectionDetail		0	0 -VertexShaderEnable			0	0  WindLightUseAtmosShaders	0	0  RenderDeferred				0	0  RenderDeferredSSAO			0	0 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index c65bc0fa50..baf0acc94b 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -108,7 +108,8 @@ const U8 AGENT_STATE_EDITING =  0x10;  // Autopilot constants  const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f;			// meters  const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f;	// meters -const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f;		// seconds +const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK = 1.5f;		// seconds +const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY = 2.5f;		// seconds. Flying is less presize, needs a bit more time  const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f;  const F64 CHAT_AGE_FAST_RATE = 3.0; @@ -878,13 +879,12 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal  }  // static -void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id) +void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp)  { -    LLViewerRegion* region = gAgent.getRegion(); -    if (region && region->getRegionID() == region_id) +    if (regionp && regionp->getRegionID() == region_id)      { -        region->requestSimulatorFeatures(); -        LLAppViewer::instance()->updateNameLookupUrl(); +        regionp->requestSimulatorFeatures(); +        LLAppViewer::instance()->updateNameLookupUrl(regionp);      }  } @@ -935,7 +935,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp)              if (regionp->capabilitiesReceived())              {                  regionp->requestSimulatorFeatures(); -                LLAppViewer::instance()->updateNameLookupUrl(); +                LLAppViewer::instance()->updateNameLookupUrl(regionp);              }              else              { @@ -961,11 +961,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp)              if (regionp->capabilitiesReceived())              { -                LLAppViewer::instance()->updateNameLookupUrl(); +                LLAppViewer::instance()->updateNameLookupUrl(regionp);              }              else              { -                regionp->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id) {LLAppViewer::instance()->updateNameLookupUrl(); }); +                regionp->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id, LLViewerRegion* regionp) {LLAppViewer::instance()->updateNameLookupUrl(regionp); });              }  		} @@ -1562,6 +1562,12 @@ void LLAgent::startAutoPilotGlobal(  	{  		return;  	} + +    if (target_global.isExactlyZero()) +    { +        LL_WARNS() << "Canceling attempt to start autopilot towards invalid position" << LL_ENDL; +        return; +    }  	// Are there any pending callbacks from previous auto pilot requests?  	if (mAutoPilotFinishedCallback) @@ -1777,7 +1783,16 @@ void LLAgent::autoPilot(F32 *delta_yaw)  		if (target_dist >= mAutoPilotTargetDist)  		{  			mAutoPilotNoProgressFrameCount++; -			if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped) +            bool out_of_time = false; +            if (getFlying()) +            { +                out_of_time = mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY * gFPSClamped; +            } +            else +            { +                out_of_time = mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK * gFPSClamped; +            } +			if (out_of_time)  			{  				stopAutoPilot();  				return; @@ -1826,7 +1841,7 @@ void LLAgent::autoPilot(F32 *delta_yaw)  		F32 slow_distance;  		if (getFlying())  		{ -			slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f); +			slow_distance = llmax(8.f, mAutoPilotStopDistance + 5.f);  		}  		else  		{ @@ -1870,14 +1885,41 @@ void LLAgent::autoPilot(F32 *delta_yaw)  		}  		else if (mAutoPilotTargetDist > mAutoPilotStopDistance)  		{ -			// walking/flying slow +            // walking/flying slow +            U32 movement_flag = 0; +  			if (at * direction > 0.9f)  			{ -				setControlFlags(AGENT_CONTROL_AT_POS); -			} -			else if (at * direction < -0.9f) -			{ -				setControlFlags(AGENT_CONTROL_AT_NEG); +                movement_flag = AGENT_CONTROL_AT_POS; +            } +            else if (at * direction < -0.9f) +            { +                movement_flag = AGENT_CONTROL_AT_NEG; +            } + +            if (getFlying()) +            { +                // flying is too fast and has high inertia, artificially slow it down +                // Don't update flags too often, server might not react +                static U64 last_time_microsec = 0; +                U64 time_microsec = LLTimer::getTotalTime(); +                U64 delta = time_microsec - last_time_microsec; +                // fly during ~0-40 ms, stop during ~40-250 ms +                if (delta > 250000) // 250ms +                { +                    // reset even if !movement_flag +                    last_time_microsec = time_microsec; +                } +                else if (delta > 40000) // 40 ms +                { +                    clearControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_AT_POS); +                    movement_flag = 0; +                } +            } + +            if (movement_flag) +            { +                setControlFlags(movement_flag);  			}  		} diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index d46c99db8c..f5ca42af5b 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -254,7 +254,7 @@ public:  	boost::signals2::connection     addParcelChangedCallback(parcel_changed_callback_t);  private: -	static void capabilityReceivedCallback(const LLUUID ®ion_id); +	static void capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp);  	typedef boost::signals2::signal<void()> parcel_changed_signal_t;  	parcel_changed_signal_t		mParcelChangedSignal; diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 134a34137b..3da87e657c 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -116,6 +116,7 @@ static const struct  };  static void setting_changed(); +static void ssl_verification_changed();  LLAppCoreHttp::HttpClass::HttpClass() @@ -195,6 +196,23 @@ void LLAppCoreHttp::init()  		LL_WARNS("Init") << "Failed to set SSL Verification.  Reason:  " << status.toString() << LL_ENDL;  	} +    // Set up Default SSL Verification option. +    const std::string no_verify_ssl("NoVerifySSLCert"); +    if (gSavedSettings.controlExists(no_verify_ssl)) +    { +        LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(no_verify_ssl); +        if (cntrl_ptr.isNull()) +        { +            LL_WARNS("Init") << "Unable to set signal on global setting '" << no_verify_ssl +                << "'" << LL_ENDL; +        } +        else +        { +            mSSLNoVerifySignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&ssl_verification_changed)); +            LLCore::HttpOptions::setDefaultSSLVerifyPeer(!cntrl_ptr->getValue().asBoolean()); +        } +    } +  	// Tracing levels for library & libcurl (note that 2 & 3 are beyond spammy):  	// 0 - None  	// 1 - Basic start, stop simple transitions @@ -296,6 +314,11 @@ void setting_changed()  	LLAppViewer::instance()->getAppCoreHttp().refreshSettings(false);  } +void ssl_verification_changed() +{ +    LLCore::HttpOptions::setDefaultSSLVerifyPeer(!gSavedSettings.getBOOL("NoVerifySSLCert")); +} +  namespace  {      // The NoOpDeletor is used when wrapping LLAppCoreHttp in a smart pointer below for @@ -355,6 +378,7 @@ void LLAppCoreHttp::cleanup()  	{  		mHttpClasses[i].mSettingsSignal.disconnect();  	} +    mSSLNoVerifySignal.disconnect();  	mPipelinedSignal.disconnect();  	delete mRequest; diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h index 95c138d598..751c498ab0 100644 --- a/indra/newview/llappcorehttp.h +++ b/indra/newview/llappcorehttp.h @@ -256,6 +256,7 @@ private:  	HttpClass					mHttpClasses[AP_COUNT];  	bool						mPipelined;				// Global setting  	boost::signals2::connection	mPipelinedSignal;		// Signal for 'HttpPipelining' setting +	boost::signals2::connection	mSSLNoVerifySignal;		// Signal for 'NoVerifySSLCert' setting  	static LLCore::HttpStatus	sslVerify(const std::string &uri, const LLCore::HttpHandler::ptr_t &handler, void *appdata);  }; diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 3f1b5139c5..aeb3294f53 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -66,6 +66,7 @@  	constructViewer();  #if defined(LL_BUGSPLAT) +    infos("bugsplat setup");  	// Engage BugsplatStartupManager *before* calling initViewer() to handle  	// any crashes during initialization.  	// https://www.bugsplat.com/docs/platforms/os-x#initialization @@ -74,6 +75,7 @@  	[BugsplatStartupManager sharedManager].delegate = self;  	[[BugsplatStartupManager sharedManager] start];  #endif +    infos("post-bugsplat setup");  	frameTimer = nil; @@ -301,9 +303,13 @@ struct AttachmentInfo      // We "happen to know" that info[0].basename is "SecondLife.old" -- due to      // the fact that BugsplatMac only notices a crash during the viewer run -    // following the crash. Replace .old with .log to reduce confusion. +    // following the crash.  +    // The Bugsplat service doesn't respect the MIME type above when returning +    // the log data to a browser, so take this opportunity to rename the file +    // from <base>.old to <base>_log.txt      info[0].basename =  -        boost::filesystem::path(info[0].pathname).stem().string() + ".log"; +        boost::filesystem::path(info[0].pathname).stem().string() + "_log.txt"; +    infos("attachmentsForBugsplatStartupManager attaching log " + info[0].basename);      NSMutableArray *attachments = [[NSMutableArray alloc] init]; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e8a3305645..9fc2e9ead8 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3626,7 +3626,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd      }      llcoro::suspend(); -    if (LLApp::isQuitting()) +    if (LLApp::isExiting())      {          return;      } @@ -3693,7 +3693,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd          LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); -        if (LLApp::isQuitting()) +        if (LLApp::isExiting())          {              return;          } @@ -3733,7 +3733,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd                  LL_WARNS("Avatar") << "Bake retry #" << retryCount << " in " << timeout << " seconds." << LL_ENDL;                  llcoro::suspendUntilTimeout(timeout);  -                if (LLApp::isQuitting()) +                if (LLApp::isExiting())                  {                      return;                  } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 053c0a5ab7..6f84b2e59f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -729,14 +729,14 @@ LLAppViewer::LLAppViewer()  	// from the previous viewer run between this constructor call and the  	// init() call, which will overwrite the static_debug_info.log file for  	// THIS run. So setDebugFileNames() early. -#if LL_BUGSPLAT +#   ifdef LL_BUGSPLAT  	// MAINT-8917: don't create a dump directory just for the  	// static_debug_info.log file  	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); -#else // ! LL_BUGSPLAT +#   else // ! LL_BUGSPLAT  	// write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.  	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); -#endif // ! LL_BUGSPLAT +#   endif // ! LL_BUGSPLAT  	mDumpPath = logdir;  	setMiniDumpDir(logdir);  	setDebugFileNames(logdir); @@ -761,17 +761,6 @@ public:  	}  }; -namespace { -// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide -// this little helper function. -void fast_exit(int rc) -{ -	_exit(rc); -} - - -} -  bool LLAppViewer::init()  { @@ -823,9 +812,9 @@ bool LLAppViewer::init()  	if (rc >= 0)  	{  		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use -		// fast_exit() rather than exit() because normal cleanup depends too +		// _exit() rather than exit() because normal cleanup depends too  		// much on successful startup! -		LLError::setFatalFunction(boost::bind(fast_exit, rc)); +		LLError::setFatalFunction([rc](const std::string&){ _exit(rc); });  	}      mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); @@ -2194,28 +2183,6 @@ bool LLAppViewer::cleanup()  	return true;  } -// A callback for LL_ERRS() to call during the watchdog error. -void watchdog_llerrs_callback(const std::string &error_string) -{ -	gLLErrorActivated = true; - -	gDebugInfo["FatalMessage"] = error_string; -	LLAppViewer::instance()->writeDebugInfo(); - -#ifdef LL_WINDOWS -	RaiseException(0,0,0,0); -#else -	raise(SIGQUIT); -#endif -} - -// A callback for the watchdog to call. -void watchdog_killer_callback() -{ -	LLError::setFatalFunction(watchdog_llerrs_callback); -	LL_ERRS() << "Watchdog killer event" << LL_ENDL; -} -  bool LLAppViewer::initThreads()  {  	static const bool enable_threads = true; @@ -2250,24 +2217,23 @@ bool LLAppViewer::initThreads()  	return true;  } -void errorCallback(const std::string &error_string) +void errorCallback(LLError::ELevel level, const std::string &error_string)  { +    if (level == LLError::LEVEL_ERROR) +    {  #ifndef LL_RELEASE_FOR_DOWNLOAD -	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); +        OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);  #endif -	//Set the ErrorActivated global so we know to create a marker file -	gLLErrorActivated = true; +        //Set the ErrorActivated global so we know to create a marker file +        gLLErrorActivated = true; -	gDebugInfo["FatalMessage"] = error_string; -	// We're not already crashing -- we simply *intend* to crash. Since we -	// haven't actually trashed anything yet, we can afford to write the whole -	// static info file. -	LLAppViewer::instance()->writeDebugInfo(); - -#ifndef SHADER_CRASH_NONFATAL -	LLError::crashAndLoop(error_string); -#endif +        gDebugInfo["FatalMessage"] = error_string; +        // We're not already crashing -- we simply *intend* to crash. Since we +        // haven't actually trashed anything yet, we can afford to write the whole +        // static info file. +        LLAppViewer::instance()->writeDebugInfo(); +    }  }  void LLAppViewer::initLoggingAndGetLastDuration() @@ -2278,7 +2244,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()  	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")                                  ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")                                  ); -	LLError::setFatalFunction(errorCallback); +	LLError::addGenericRecorder(&errorCallback);  	//LLError::setTimeFunction(getRuntime);  	// Remove the last ".old" log file. @@ -3037,11 +3003,16 @@ bool LLAppViewer::initWindow()  		use_watchdog = bool(watchdog_enabled_setting);  	} +	LL_INFOS("AppInit") << "watchdog" +						<< (use_watchdog ? " " : " NOT ") +						<< "enabled" +						<< " (setting = " << watchdog_enabled_setting << ")" +						<< LL_ENDL; +  	if (use_watchdog)  	{ -		LLWatchdog::getInstance()->init(watchdog_killer_callback); +		LLWatchdog::getInstance()->init();  	} -	LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL;  	LLNotificationsUI::LLNotificationManager::getInstance(); @@ -3474,8 +3445,8 @@ void LLAppViewer::writeSystemInfo()  	gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();  	gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); -	gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value()); -	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>()); +	gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value()); +	gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());  	gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple();  	// The user is not logged on yet, but record the current grid choice login url @@ -3488,12 +3459,18 @@ void LLAppViewer::writeSystemInfo()  	gDebugInfo["MainloopThreadID"] = (S32)thread_id;  #endif +#ifndef LL_BUGSPLAT  	// "CrashNotHandled" is set here, while things are running well,  	// in case of a freeze. If there is a freeze, the crash logger will be launched  	// and can read this value from the debug_info.log.  	// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,  	// then the value of "CrashNotHandled" will be set to true. -	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; +	gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true); +#else // LL_BUGSPLAT +	// "CrashNotHandled" is obsolete; it used (not very successsfully) +    // to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze +	gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false); +#endif // ! LL_BUGSPLAT  	// Insert crash host url (url to post crash log to) if configured. This insures  	// that the crash report will go to the proper location in the case of a @@ -3524,7 +3501,7 @@ void LLAppViewer::writeSystemInfo()      gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");  	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();  	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); -	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); +	gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin());  	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");      gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); @@ -3654,7 +3631,7 @@ void LLAppViewer::handleViewerCrash()  	// The crash is being handled here so set this value to false.  	// Otherwise the crash logger will think this crash was a freeze. -	gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false; +	gDebugInfo["Dynamic"]["CrashNotHandled"] = LLSD::Boolean(false);  	//Write out the crash status file  	//Use marker file style setup, as that's the simplest, especially since @@ -3727,6 +3704,8 @@ void LLAppViewer::handleViewerCrash()  	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]); +	gDebugInfo["FatalMessage"] = LLError::getFatalMessage(); +  	// Close the debug file  	pApp->writeDebugInfo(false);  //false answers the isStatic question with the least overhead.  } @@ -3825,9 +3804,8 @@ void LLAppViewer::processMarkerFiles()  		else if (marker_is_same_version)  		{  			// the file existed, is ours, and matched our version, so we can report on what it says -			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL; -			gLastExecEvent = LAST_EXEC_FROZE; - +			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL; +			gLastExecEvent = LAST_EXEC_OTHER_CRASH;  		}  		else  		{ @@ -5371,10 +5349,9 @@ void LLAppViewer::sendLogoutRequest()  	}  } -void LLAppViewer::updateNameLookupUrl() +void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp)  { -    LLViewerRegion* region = gAgent.getRegion(); -    if (!region || !region->capabilitiesReceived()) +    if (!regionp || !regionp->capabilitiesReceived())      {          return;      } @@ -5383,7 +5360,7 @@ void LLAppViewer::updateNameLookupUrl()      bool had_capability = LLAvatarNameCache::getInstance()->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)      { @@ -5694,6 +5671,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(); +} +  void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)  {  	if(!mMainloopTimeout) @@ -5737,11 +5741,6 @@ void LLAppViewer::pauseMainloopTimeout()  void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)  { -//	if(!restoreErrorTrap()) -//	{ -//		LL_WARNS() << "!!!!!!!!!!!!! Its an error trap!!!!" << state << LL_ENDL; -//	} -  	if(mMainloopTimeout)  	{  		if(secs < 0.0f) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 5ceb540784..0afb70958c 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -57,6 +57,7 @@ class LLImageDecodeThread;  class LLTextureFetch;  class LLWatchdogTimeout;  class LLViewerJoystick; +class LLViewerRegion;  extern LLTrace::BlockTimerStatHandle FTM_FRAME; @@ -150,6 +151,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, @@ -209,7 +212,7 @@ public:  	// llcorehttp init/shutdown/config information.  	LLAppCoreHttp & getAppCoreHttp()			{ return mAppCoreHttp; } -    void updateNameLookupUrl(); +    void updateNameLookupUrl(const LLViewerRegion* regionp);  protected:  	virtual bool initWindow(); // Initialize the viewer's window. diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 662164af2d..42946e4415 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -68,39 +68,21 @@ namespace  	int gArgC;  	char** gArgV;  	LLAppViewerMacOSX* gViewerAppPtr = NULL; - -    void (*gOldTerminateHandler)() = NULL;      std::string gHandleSLURL;  } -static void exceptionTerminateHandler() -{ -	// reinstall default terminate() handler in case we re-terminate. -	if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler); -	// treat this like a regular viewer crash, with nice stacktrace etc. -    long *null_ptr; -    null_ptr = 0; -    *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad. -	//LLAppViewer::handleViewerCrash(); -	// we've probably been killed-off before now, but... -	gOldTerminateHandler(); // call old terminate() handler -} -  void constructViewer()  {  	// Set the working dir to <bundle>/Contents/Resources  	if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1)  	{ -		LL_WARNS() << "Could not change directory to " +		LL_WARNS("InitOSX") << "Could not change directory to "  				<< gDirUtilp->getAppRODataDir() << ": " << strerror(errno)  				<< LL_ENDL;  	}  	gViewerAppPtr = new LLAppViewerMacOSX(); -    // install unexpected exception handler -	gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); -  	gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);  } @@ -109,7 +91,7 @@ bool initViewer()  	bool ok = gViewerAppPtr->init();  	if(!ok)  	{ -		LL_WARNS() << "Application init failed." << LL_ENDL; +		LL_WARNS("InitOSX") << "Application init failed." << LL_ENDL;  	}  	else if (!gHandleSLURL.empty())  	{ @@ -172,7 +154,7 @@ class CrashMetadataSingleton: public CrashMetadata, public LLSingleton<CrashMeta      std::string get_metadata(const LLSD& info, const LLSD::String& key) const      {          std::string data(info[key].asString()); -        LL_INFOS() << "  " << key << "='" << data << "'" << LL_ENDL; +        LL_INFOS("Bugsplat") << "  " << key << "='" << data << "'" << LL_ENDL;          return data;      }  }; @@ -188,22 +170,22 @@ CrashMetadataSingleton::CrashMetadataSingleton()      LLSD info;      if (! static_file.is_open())      { -        LL_INFOS() << "Can't open '" << staticDebugPathname +        LL_WARNS("Bugsplat") << "Can't open '" << staticDebugPathname                     << "'; no metadata about previous run" << LL_ENDL;      }      else if (! LLSDSerialize::deserialize(info, static_file, LLSDSerialize::SIZE_UNLIMITED))      { -        LL_INFOS() << "Can't parse '" << staticDebugPathname +        LL_WARNS("Bugsplat") << "Can't parse '" << staticDebugPathname                     << "'; no metadata about previous run" << LL_ENDL;      }      else      { -        LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL; -        logFilePathname         = get_metadata(info, "SLLog"); -        userSettingsPathname    = get_metadata(info, "SettingsFilename"); +        LL_INFOS("Bugsplat") << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL; +        logFilePathname      = get_metadata(info, "SLLog"); +        userSettingsPathname = get_metadata(info, "SettingsFilename");          accountSettingsPathname = get_metadata(info, "PerAccountSettingsFilename"); -        OSInfo                  = get_metadata(info, "OSInfo"); -        agentFullname           = get_metadata(info, "LoginName"); +        OSInfo               = get_metadata(info, "OSInfo"); +        agentFullname        = get_metadata(info, "LoginName");          // Translate underscores back to spaces          LLStringUtil::replaceChar(agentFullname, '_', ' ');          regionName           = get_metadata(info, "CurrentRegion"); @@ -219,7 +201,7 @@ CrashMetadata& CrashMetadata_instance()  void infos(const std::string& message)  { -    LL_INFOS() << message << LL_ENDL; +    LL_INFOS("InitOSX", "Bugsplat") << message << LL_ENDL;  }  int main( int argc, char **argv )  @@ -242,14 +224,11 @@ bool LLAppViewerMacOSX::init()  {  	bool success = LLAppViewer::init(); -#if LL_SEND_CRASH_REPORTS      if (success)      {          LLAppViewer* pApp = LLAppViewer::instance();          pApp->initCrashReporting();      } -#endif -          return success;  } @@ -334,11 +313,12 @@ bool LLAppViewerMacOSX::restoreErrorTrap()  	unsigned int reset_count = 0; -#define SET_SIG(S) 	sigaction(SIGABRT, &act, &old_act); \ -					if(act.sa_sigaction != old_act.sa_sigaction) \ -						++reset_count; +#define SET_SIG(SIGNAL) sigaction(SIGNAL, &act, &old_act); \ +                        if(act.sa_sigaction != old_act.sa_sigaction) ++reset_count;  	// Synchronous signals -	SET_SIG(SIGABRT) +#   ifndef LL_BUGSPLAT +	SET_SIG(SIGABRT) // let bugsplat catch this +#   endif          	SET_SIG(SIGALRM)  	SET_SIG(SIGBUS)  	SET_SIG(SIGFPE) @@ -369,6 +349,10 @@ bool LLAppViewerMacOSX::restoreErrorTrap()  void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)  { +#if defined LL_BUGSPLAT +    LL_DEBUGS("InitOSX", "Bugsplat") << "using BugSplat crash logger" << LL_ENDL; +#elif LL_SEND_CRASH_REPORTS +    LL_DEBUGS("InitOSX") << "Initializing legacy crash logger" << LL_ENDL;  	std::string command_str = "mac-crash-logger.app";      std::stringstream pid_str; @@ -380,6 +364,9 @@ void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)      LL_WARNS() << "about to launch mac-crash-logger" << pid_str.str()                 << " " << logdir << " " << appname << LL_ENDL;      launchApplication(&command_str, &args); +#else +    LL_DEBUGS("InitOSX") << "No crash logger enabled" << LL_ENDL;     +#endif // ! LL_BUGSPLAT  }  std::string LLAppViewerMacOSX::generateSerialNumber() @@ -391,7 +378,8 @@ std::string LLAppViewerMacOSX::generateSerialNumber()  	CFStringRef serialNumber = NULL;  	io_service_t    platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,  																 IOServiceMatching("IOPlatformExpertDevice")); -	if (platformExpert) { +	if (platformExpert) +    {  		serialNumber = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,  																	 CFSTR(kIOPlatformSerialNumberKey),  																	 kCFAllocatorDefault, 0);		 diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 9b1c0d1f8b..9daea515e5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -177,7 +177,7 @@ static void exceptionTerminateHandler()      long *null_ptr;      null_ptr = 0;      *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad. -	//LLAppViewer::handleViewerCrash(); +  	// we've probably been killed-off before now, but...  	gOldTerminateHandler(); // call old terminate() handler  } @@ -365,10 +365,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,  	viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); -#if LL_SEND_CRASH_REPORTS  -	// ::SetUnhandledExceptionFilter(catchallCrashHandler);  -#endif -  	// Set a debug info flag to indicate if multiple instances are running.  	bool found_other_instance = !create_app_mutex();  	gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance); @@ -609,6 +605,13 @@ bool LLAppViewerWin32::init()  #else // LL_BUGSPLAT  #pragma message("Building with BugSplat") +    if (!isSecondInstance()) +    { +        // Cleanup previous session +        std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log"); +        LLFile::remove(log_file, ENOENT); +    } +  	std::string build_data_fname(  		gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));  	// Use llifstream instead of std::ifstream because LL_PATH_EXECUTABLE @@ -616,7 +619,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 @@ -626,7 +629,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 @@ -634,7 +637,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 @@ -645,18 +648,35 @@ bool LLAppViewerWin32::init()  													   LL_VIEWER_VERSION_PATCH << '.' <<  													   LL_VIEWER_VERSION_BUILD)); +                DWORD dwFlags = 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 -					MDSF_NONINTERACTIVE | // automatically submit report without prompting -					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 @@ -685,6 +705,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(); @@ -813,8 +843,7 @@ bool LLAppViewerWin32::beingDebugged()  bool LLAppViewerWin32::restoreErrorTrap()  {	 -	return true; -	//return LLWinDebug::checkExceptionHandler(); +	return true; // we don't check for handler collisions on windows, so just say they're ok  }  void LLAppViewerWin32::initCrashReporting(bool reportFreeze) diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index c5fae6a3a3..83ae875a15 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/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 3aaaaf52f5..bf10a9f2b4 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -347,7 +347,7 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren  bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,      const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)  { -    if (LLApp::isQuitting()) +    if (LLApp::isExiting())      {          // Reply from coroutine came on shutdown          // We are quiting, don't start any more coroutines! diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp index ef1b644ad4..934a38bb8e 100644 --- a/indra/newview/lldelayedgestureerror.cpp +++ b/indra/newview/lldelayedgestureerror.cpp @@ -113,7 +113,7 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)  		}  	} -	if(!LLApp::isQuitting()) +	if(!LLApp::isExiting())  	{  		LLNotificationsUtil::add(ent.mNotifyName, args);  	} diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 74c1b99e4d..79f72220ed 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1029,7 +1029,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(); @@ -1154,9 +1154,38 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm      }      else if (!environment->getSky())      { -        LL_DEBUGS("ENVIRONMENT") << "Blank sky for " << env_selection_to_string(env) << ". Reusing environment for sky." << LL_ENDL; -        environment->setSky(mCurrentEnvironment->getSky()); -        environment->setFlags(DayInstance::NO_ANIMATE_SKY); +        if (mCurrentEnvironment->getEnvironmentSelection() != ENV_NONE) +        { +            // Note: This looks suspicious. Shouldn't we assign whole day if mCurrentEnvironment has whole day? +            // and then add water/sky on top +            // This looks like it will result in sky using single keyframe instead of whole day if day is present +            // when setting static water without static sky +            environment->setSky(mCurrentEnvironment->getSky()); +            environment->setFlags(DayInstance::NO_ANIMATE_SKY); +        } +        else +        { +            // Environment is not properly initialized yet, but we should have environment by this point +            DayInstance::ptr_t substitute = getEnvironmentInstance(ENV_PARCEL, true); +            if (!substitute || !substitute->getSky()) +            { +                substitute = getEnvironmentInstance(ENV_REGION, true); +            } +            if (!substitute || !substitute->getSky()) +            { +                substitute = getEnvironmentInstance(ENV_DEFAULT, true); +            } + +            if (substitute && substitute->getSky()) +            { +                environment->setSky(substitute->getSky()); +                environment->setFlags(DayInstance::NO_ANIMATE_SKY); +            } +            else +            { +                LL_WARNS("ENVIRONMENT") << "Failed to assign substitute water/sky, environment is not properly initialized" << LL_ENDL; +            } +        }      }      if (fixed.second) @@ -1167,9 +1196,38 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm      }      else if (!environment->getWater())      { -        LL_DEBUGS("ENVIRONMENT") << "Blank water for " << env_selection_to_string(env) << ". Reusing environment for water." << LL_ENDL; -        environment->setWater(mCurrentEnvironment->getWater()); -        environment->setFlags(DayInstance::NO_ANIMATE_WATER); +        if (mCurrentEnvironment->getEnvironmentSelection() != ENV_NONE) +        { +            // Note: This looks suspicious. Shouldn't we assign whole day if mCurrentEnvironment has whole day? +            // and then add water/sky on top +            // This looks like it will result in water using single keyframe instead of whole day if day is present +            // when setting static sky without static water +            environment->setWater(mCurrentEnvironment->getWater()); +            environment->setFlags(DayInstance::NO_ANIMATE_WATER); +        } +        else +        { +            // Environment is not properly initialized yet, but we should have environment by this point +            DayInstance::ptr_t substitute = getEnvironmentInstance(ENV_PARCEL, true); +            if (!substitute || !substitute->getWater()) +            { +                substitute = getEnvironmentInstance(ENV_REGION, true); +            } +            if (!substitute || !substitute->getWater()) +            { +                substitute = getEnvironmentInstance(ENV_DEFAULT, true); +            } + +            if (substitute && substitute->getWater()) +            { +                environment->setWater(substitute->getWater()); +                environment->setFlags(DayInstance::NO_ANIMATE_WATER); +            } +            else +            { +                LL_WARNS("ENVIRONMENT") << "Failed to assign substitute water/sky, environment is not properly initialized" << LL_ENDL; +            } +        }      }      if (!mSignalEnvChanged.empty()) @@ -1698,8 +1756,11 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI          }          else          { -            setEnvironment(ENV_REGION, envinfo->mDayCycle, envinfo->mDayLength, envinfo->mDayOffset, envinfo->mEnvVersion);              mTrackAltitudes = envinfo->mAltitudes; +            // update track selection based on new altitudes +            mCurrentTrack = calculateSkyTrackForAltitude(gAgent.getPositionAgent().mV[VZ]); + +            setEnvironment(ENV_REGION, envinfo->mDayCycle, envinfo->mDayLength, envinfo->mDayOffset, envinfo->mEnvVersion);          }          LL_DEBUGS("ENVIRONMENT") << "Altitudes set to {" << mTrackAltitudes[0] << ", "<< mTrackAltitudes[1] << ", " << mTrackAltitudes[2] << ", " << mTrackAltitudes[3] << LL_ENDL; @@ -1931,6 +1992,10 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ      {          LL_WARNS("ENVIRONMENT") << "Couldn't retrieve environment settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;      } +    else if (LLApp::isExiting()) +    { +        return; +    }      else      {          LLSD environment = result[KEY_ENVIRONMENT]; @@ -2020,6 +2085,10 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf          notify = LLSD::emptyMap();          notify["FAIL_REASON"] = result["message"].asString();      } +    else if (LLApp::isExiting()) +    { +        return; +    }      else      {          LLSD environment = result[KEY_ENVIRONMENT]; @@ -2082,6 +2151,10 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen          notify = LLSD::emptyMap();          notify["FAIL_REASON"] = result["message"].asString();      } +    else if (LLApp::isExiting()) +    { +        return; +    }      else      {         LLSD environment = result[KEY_ENVIRONMENT]; @@ -2319,6 +2392,15 @@ void LLEnvironment::onAgentPositionHasChanged(const LLVector3 &localpos)          return;      mCurrentTrack = trackno; + +    LLViewerRegion* cur_region = gAgent.getRegion(); +    if (!cur_region || !cur_region->capabilitiesReceived()) +    { +        // Environment not ready, environment will be updated later, don't cause 'blend' yet. +        // But keep mCurrentTrack updated in case we won't get new altitudes for some reason +        return; +    } +      for (S32 env = ENV_LOCAL; env < ENV_DEFAULT; ++env)      {          if (mEnvironments[env]) diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 171858e472..1fbd198019 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -236,6 +236,7 @@ void LLFloaterAbout::fetchServerReleaseNotesCoro(const std::string& cap_url)      httpOpts->setWantHeaders(true);      httpOpts->setFollowRedirects(false); +    httpOpts->setSSLVerifyPeer(false); // We want this data even if SSL verification fails      LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts); diff --git a/indra/newview/llfloatereditenvironmentbase.cpp b/indra/newview/llfloatereditenvironmentbase.cpp index e888144b6a..2850951668 100644 --- a/indra/newview/llfloatereditenvironmentbase.cpp +++ b/indra/newview/llfloatereditenvironmentbase.cpp @@ -262,7 +262,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons          {              const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);              LLUUID parent_id = mInventoryItem->getParentUUID(); -            if (marketplacelistings_id == parent_id) +            if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))              {                  parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);              } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 2c9a8e64b7..a99a096ea7 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -211,6 +211,20 @@ bool LLFloaterExperienceProfile::experiencePermission( LLHandle<LLFloaterExperie      return false;  } +bool LLFloaterExperienceProfile::matchesKey(const LLSD& key) +{ +    if (key.has("experience_id")) +    { +        return mExperienceId == key["experience_id"].asUUID(); +    } +    else if (key.isUUID()) +    { +        return mExperienceId == key.asUUID(); +    } +    // Assume NULL uuid +    return mExperienceId.isNull(); +} +  void LLFloaterExperienceProfile::onClickEdit()  { diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h index 1394418d91..f9b6e2e2eb 100644 --- a/indra/newview/llfloaterexperienceprofile.h +++ b/indra/newview/llfloaterexperienceprofile.h @@ -51,6 +51,8 @@ public:      LLFloaterExperienceProfile(const LLSD& data);      virtual ~LLFloaterExperienceProfile(); +     +    /* virtual */ bool matchesKey(const LLSD& key);      LLUUID getExperienceId() const { return mExperienceId; }      void setPreferences( const LLSD& content ); diff --git a/indra/newview/llfloatergridstatus.cpp b/indra/newview/llfloatergridstatus.cpp index faa7e9f3db..9745e17bbb 100644 --- a/indra/newview/llfloatergridstatus.cpp +++ b/indra/newview/llfloatergridstatus.cpp @@ -95,6 +95,7 @@ void LLFloaterGridStatus::getGridStatusRSSCoro()      LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);      LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); +    httpOpts->setSSLVerifyPeer(false); // We want this data even if SSL fails      httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);      std::string url = gSavedSettings.getString("GridStatusRSS"); diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index f2efef0c33..63bce3d2eb 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -122,8 +122,7 @@ void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_  		}  	} -	// Decrement the cursor -	getWindow()->decBusyCount(); +  	getChildView("loading_label")->setVisible( false);  	closeFloater();  } @@ -302,3 +301,9 @@ bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const  	}  	return false;  } + +void LLFloaterURLEntry::onClose( bool app_quitting ) +{ +    // Decrement the cursor +    getWindow()->decBusyCount(); +} diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h index 20f4604907..04a8eca069 100644 --- a/indra/newview/llfloaterurlentry.h +++ b/indra/newview/llfloaterurlentry.h @@ -42,6 +42,7 @@ public:  	// that panel via the handle.  	static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url);  	/*virtual*/	BOOL	postBuild(); +    /*virtual*/ void onClose( bool app_quitting );  	void headerFetchComplete(S32 status, const std::string& mime_type);  	bool addURLToCombobox(const std::string& media_url); diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 4ed802138d..9d49c30a49 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -105,6 +105,9 @@ LLHUDNameTag::LLHUDNameTag(const U8 type)  {  	LLPointer<LLHUDNameTag> ptr(this);  	sTextObjects.insert(ptr); + +    mRoundedRectImgp = LLUI::getUIImage("Rounded_Rect"); +    mRoundedRectTopImgp = LLUI::getUIImage("Rounded_Rect_Top");  }  LLHUDNameTag::~LLHUDNameTag() @@ -274,9 +277,6 @@ void LLHUDNameTag::renderText(BOOL for_select)  	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); -	// *TODO: cache this image -	LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Rect"); -  	// *TODO: make this a per-text setting  	LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");  	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); @@ -306,17 +306,16 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);  	LLRect screen_rect;  	screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); -	imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); +    mRoundedRectImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color);  	if (mLabelSegments.size())  	{ -		LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top");  		LLRect label_top_rect = screen_rect;  		const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f)));  		label_top_rect.mBottom = label_top_rect.mTop - label_height;  		LLColor4 label_top_color = text_color;  		label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; -		rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); +        mRoundedRectTopImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);  	}  	F32 y_offset = (F32)mOffsetY; diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 20272a8232..7577dd5de6 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -40,8 +40,8 @@  #include <set>  #include <vector> -class LLDrawable;  class LLHUDNameTag; +class LLUIImage;  struct llhudnametag_further_away  { @@ -171,6 +171,8 @@ private:  	EVertAlignment	mVertAlignment;  	S32				mLOD;  	BOOL			mHidden; +	LLPointer<LLUIImage> mRoundedRectImgp; +	LLPointer<LLUIImage> mRoundedRectTopImgp;  	static BOOL    sDisplayText ;  	static std::set<LLPointer<LLHUDNameTag> > sTextObjects; diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 72d28a3d44..7c957ac712 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -138,9 +138,6 @@ void LLHUDText::renderText()  	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); -	// *TODO: cache this image -	LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); -  	// *TODO: make this a per-text setting  	LLColor4 bg_color = LLUIColorTable::instance().getColor("ObjectBubbleColor");  	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d35d8456be..a729b276d5 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3987,6 +3987,12 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items  	const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);  	const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);  	const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); +	const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + +	if (outfits_id == mUUID) +	{ +		items.push_back(std::string("New Outfit")); +	}  	if (lost_and_found_id == mUUID)  	{ @@ -4085,7 +4091,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items  		// Not sure what the right thing is to do here.  		if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))  		{ -			if (!isInboxFolder()) // don't allow creation in inbox +			if (!isInboxFolder() // don't allow creation in inbox +				&& outfits_id != mUUID)  			{  				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.  				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 543d2a087f..921b80a667 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -132,36 +132,49 @@ void LLLandmarkList::processGetAssetReply(  		LLVFile file(vfs, uuid, type);  		S32 file_length = file.getSize(); -		std::vector<char> buffer(file_length + 1); -		file.read( (U8*)&buffer[0], file_length); -		buffer[ file_length ] = 0; +        if (file_length > 0) +        { +            std::vector<char> buffer(file_length + 1); +            file.read((U8*)&buffer[0], file_length); +            buffer[file_length] = 0; -		LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0]); -		if (landmark) -		{ -			gLandmarkList.mList[ uuid ] = landmark; -			gLandmarkList.mRequestedList.erase(uuid); -			 -			LLVector3d pos; -			if(!landmark->getGlobalPos(pos)) -			{ -				LLUUID region_id; -				if(landmark->getRegionID(region_id)) -				{ -					LLLandmark::requestRegionHandle( -						gMessageSystem, -						gAgent.getRegionHost(), -						region_id, -						boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid)); -				} - -				// the callback will be called when we get the region handle. -			} -			else -			{ -				gLandmarkList.makeCallbacks(uuid); -			} -		} +            LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0], buffer.size()); +            if (landmark) +            { +                gLandmarkList.mList[uuid] = landmark; +                gLandmarkList.mRequestedList.erase(uuid); + +                LLVector3d pos; +                if (!landmark->getGlobalPos(pos)) +                { +                    LLUUID region_id; +                    if (landmark->getRegionID(region_id)) +                    { +                        LLLandmark::requestRegionHandle( +                            gMessageSystem, +                            gAgent.getRegionHost(), +                            region_id, +                            boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid)); +                    } + +                    // the callback will be called when we get the region handle. +                } +                else +                { +                    gLandmarkList.makeCallbacks(uuid); +                } +            } +            else +            { +                // failed to parse, shouldn't happen +                gLandmarkList.eraseCallbacks(uuid); +            } +        } +        else +        { +            // got a good status, but no file, shouldn't happen +            gLandmarkList.eraseCallbacks(uuid); +        }  	}  	else  	{ @@ -179,7 +192,7 @@ void LLLandmarkList::processGetAssetReply(  		gLandmarkList.mBadList.insert(uuid);          gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests -        // todo: this should clean mLoadedCallbackMap! +        gLandmarkList.eraseCallbacks(uuid);  	}      // getAssetData can fire callback immediately, causing @@ -223,32 +236,39 @@ BOOL LLLandmarkList::assetExists(const LLUUID& asset_uuid)  void LLLandmarkList::onRegionHandle(const LLUUID& landmark_id)  {  	LLLandmark* landmark = getAsset(landmark_id); - -	if (!landmark) -	{ -		LL_WARNS() << "Got region handle but the landmark not found." << LL_ENDL; -		return; -	} +    if (!landmark) +    { +        LL_WARNS() << "Got region handle but the landmark " << landmark_id << " not found." << LL_ENDL; +        eraseCallbacks(landmark_id); +        return; +    }  	// Calculate landmark global position.  	// This should succeed since the region handle is available.  	LLVector3d pos;  	if (!landmark->getGlobalPos(pos))  	{ -		LL_WARNS() << "Got region handle but the landmark global position is still unknown." << LL_ENDL; -		return; +        LL_WARNS() << "Got region handle but the landmark " << landmark_id << " global position is still unknown." << LL_ENDL; +        eraseCallbacks(landmark_id); +        return;  	} +    // Call this even if no landmark exists to clean mLoadedCallbackMap  	makeCallbacks(landmark_id);  } +void LLLandmarkList::eraseCallbacks(const LLUUID& landmark_id) +{ +    mLoadedCallbackMap.erase(landmark_id); +} +  void LLLandmarkList::makeCallbacks(const LLUUID& landmark_id)  {  	LLLandmark* landmark = getAsset(landmark_id);  	if (!landmark)  	{ -		LL_WARNS() << "Landmark to make callbacks for not found." << LL_ENDL; +		LL_WARNS() << "Landmark " << landmark_id << " to make callbacks for not found." << LL_ENDL;  	}  	// make all the callbacks here. diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h index 2e7bd25610..4f3b11660d 100644 --- a/indra/newview/lllandmarklist.h +++ b/indra/newview/lllandmarklist.h @@ -65,6 +65,7 @@ public:  protected:  	void onRegionHandle(const LLUUID& landmark_id); +	void eraseCallbacks(const LLUUID& landmark_id);  	void makeCallbacks(const LLUUID& landmark_id);  	typedef std::map<LLUUID, LLLandmark*> landmark_list_t; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 958c76f261..bd24c47a4f 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -31,6 +31,7 @@  #include "lluictrl.h"  #include "llframetimer.h" +#include "llnotificationptr.h"  class LLViewBorder;  class LLUICtrlFactory; @@ -145,7 +146,7 @@ public:  		void setTextureSize(S32 width, S32 height); -		void showNotification(boost::shared_ptr<class LLNotification> notify); +		void showNotification(LLNotificationPtr notify);  		void hideNotification();  		void setTrustedContent(bool trusted); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 3e8731dfe6..2c1c1191da 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -881,7 +881,7 @@ void LLMeshRepoThread::run()  		LL_WARNS(LOG_MESH) << "Convex decomposition unable to be loaded.  Expect severe problems." << LL_ENDL;  	} -	while (!LLApp::isQuitting()) +	while (!LLApp::isExiting())  	{  		// *TODO:  Revise sleep/wake strategy and try to move away  		// from polling operations in this thread.  We can sleep @@ -898,7 +898,7 @@ void LLMeshRepoThread::run()  		mSignal->wait(); -		if (LLApp::isQuitting()) +		if (LLApp::isExiting())  		{  			break;  		} @@ -1168,7 +1168,7 @@ void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id)  void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  { -	if (!LLAppViewer::isQuitting()) +	if (!LLAppViewer::isExiting())  	{  		loadMeshLOD(mesh_params, lod);  	} @@ -2654,7 +2654,7 @@ void LLMeshUploadThread::doWholeModelUpload()  			LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL;  			mHttpRequest->update(0); -			while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) +			while (! LLApp::isExiting() && ! finished() && ! isDiscarded())  			{  				ms_sleep(sleep_time);  				sleep_time = llmin(250U, sleep_time + sleep_time); @@ -2703,7 +2703,7 @@ void LLMeshUploadThread::requestWholeModelFee()  		U32 sleep_time(10);  		mHttpRequest->update(0); -		while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) +		while (! LLApp::isExiting() && ! finished() && ! isDiscarded())  		{  			ms_sleep(sleep_time);  			sleep_time = llmin(250U, sleep_time + sleep_time); @@ -3149,7 +3149,7 @@ common_exit:  LLMeshHeaderHandler::~LLMeshHeaderHandler()  { -	if (!LLApp::isQuitting()) +	if (!LLApp::isExiting())  	{  		if (! mProcessed)  		{ @@ -3292,7 +3292,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b  LLMeshLODHandler::~LLMeshLODHandler()  { -	if (! LLApp::isQuitting()) +	if (! LLApp::isExiting())  	{  		if (! mProcessed)  		{ @@ -3553,7 +3553,7 @@ void LLMeshRepository::shutdown()  		mUploads[i]->discard() ; //discard the uploading requests.  	} -	mThread->mSignal->signal(); +	mThread->mSignal->broadcast();  	while (!mThread->isStopped())  	{ @@ -4682,7 +4682,8 @@ void LLPhysicsDecomp::shutdown()  	if (mSignal)  	{  		mQuitting = true; -		mSignal->signal(); +		// There is only one wait(), but just in case 'broadcast' +		mSignal->broadcast();  		while (!isStopped())  		{ diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 272e7ae351..c1b622ffff 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -67,6 +67,7 @@ LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p)        mOutfitsObserver(NULL),        mScrollPanel(NULL),        mGalleryPanel(NULL), +      mLastRowPanel(NULL),        mGalleryCreated(false),        mRowCount(0),        mItemsAddedCount(0), @@ -166,9 +167,7 @@ bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)          std::string name1 = item1->getItemName();          std::string name2 = item2->getItemName(); -        LLStringUtil::toUpper(name1); -        LLStringUtil::toUpper(name2); -        return name1 < name2; +        return (LLStringUtil::compareDict(name1, name2) < 0);      }      else      { @@ -241,7 +240,15 @@ void LLOutfitGallery::removeLastRow()      mGalleryPanel->removeChild(mLastRowPanel);      mUnusedRowPanels.push_back(mLastRowPanel);      mRowPanels.pop_back(); -    mLastRowPanel = mRowPanels.back(); +    if (mRowPanels.size() > 0) +    { +        // Just removed last row +        mLastRowPanel = mRowPanels.back(); +    } +    else +    { +        mLastRowPanel = NULL; +    }  }  LLPanel* LLOutfitGallery::addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap) @@ -1111,7 +1118,7 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)          }      } -    if (mGalleryCreated && !LLApp::isQuitting()) +    if (mGalleryCreated && !LLApp::isExiting())      {          reArrangeRows();      } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 71ab826e1c..423e57978a 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -59,10 +59,7 @@ bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LL  	std::string name1 = tab1->getTitle();  	std::string name2 = tab2->getTitle(); -	LLStringUtil::toUpper(name1); -	LLStringUtil::toUpper(name2); - -	return name1 < name2; +    return (LLStringUtil::compareDict(name1, name2) < 0);  }  struct outfit_accordion_tab_params : public LLInitParam::Block<outfit_accordion_tab_params, LLAccordionCtrlTab::Params> diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 3964dc075c..381b80fb66 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -254,7 +254,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	LLLineEditor* password_edit(getChild<LLLineEditor>("password_edit"));  	password_edit->setKeystrokeCallback(onPassKey, this);  	// STEAM-14: When user presses Enter with this field in focus, initiate login -	password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, this)); +	password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, false));  	// change z sort of clickable text to be behind buttons  	sendChildToBack(getChildView("forgot_password_text")); @@ -265,7 +265,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,      {          LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");          updateLocationSelectorsVisibility(); // separate so that it can be called from preferences -        favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this)); +        favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, false));          favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));          LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo"); @@ -458,6 +458,9 @@ void LLPanelLogin::addFavoritesToStartLocation()  	if (combo->getValue().asString().empty())  	{  		combo->selectFirstItem(); +        // Value 'home' or 'last' should have been taken from NextLoginLocation +        // but NextLoginLocation was not set, so init it from combo explicitly +        onLocationSLURL();  	}  } @@ -1004,12 +1007,15 @@ void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev  // Protected methods  //---------------------------------------------------------------------------  // static -void LLPanelLogin::onClickConnect(void *) +void LLPanelLogin::onClickConnect(bool commit_fields)  {  	if (sInstance && sInstance->mCallback)  	{ -		// JC - Make sure the fields all get committed. -		sInstance->setFocus(FALSE); +		if (commit_fields) +		{ +			// JC - Make sure the fields all get committed. +			sInstance->setFocus(FALSE); +		}  		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");  		LLSD combo_val = combo->getSelectedValue(); @@ -1132,7 +1138,7 @@ void LLPanelLogin::onUserListCommit(void*)             }             else             { -               onClickConnect(NULL); +               onClickConnect();             }          }      } @@ -1364,6 +1370,7 @@ void LLPanelLogin::onSelectServer()  			{  				// the grid specified by the location is not this one, so clear the combo  				location_combo->setCurrentByIndex(0); // last location on the new grid +				onLocationSLURL();  			}  		}			  		break; diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 788c269ffd..c5e6b41def 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -99,7 +99,7 @@ private:  	static void setFields(LLPointer<LLCredential> credential); -	static void onClickConnect(void*); +	static void onClickConnect(bool commit_fields = true);  	static void onClickNewAccount(void*);  	static void onClickVersion(void*);  	static void onClickForgotPassword(void*); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 4762e15d8f..8294977f99 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -483,19 +483,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)  		mNoClassifieds = !mClassifiedsList->size();  	} -	bool no_data = mNoPicks && mNoClassifieds; -	mNoItemsLabel->setVisible(no_data); -	if (no_data) -	{ -		if(getAvatarId() == gAgentID) -		{ -			mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText")); -		} -		else -		{ -			mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText")); -		} -	} +    updateNoItemsLabel();  }  LLPickItem* LLPanelPicks::getSelectedPickItem() @@ -724,6 +712,13 @@ bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& resp  	{  		LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]);  		mPicksList->removeItemByValue(pick_value); +         +        mNoPicks = !mPicksList->size(); +        if (mNoPicks) +        { +            showAccordion("tab_picks", false); +        } +        updateNoItemsLabel();  	}  	updateButtons();  	return false; @@ -738,6 +733,13 @@ bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD  	{  		LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]);  		mClassifiedsList->removeItemByValue(value); + +        mNoClassifieds = !mClassifiedsList->size(); +        if (mNoClassifieds) +        { +            showAccordion("tab_classifieds", false); +        } +        updateNoItemsLabel();  	}  	updateButtons();  	return false; @@ -851,6 +853,23 @@ void LLPanelPicks::updateButtons()  	}  } +void LLPanelPicks::updateNoItemsLabel() +{ +    bool no_data = mNoPicks && mNoClassifieds; +    mNoItemsLabel->setVisible(no_data); +    if (no_data) +    { +        if (getAvatarId() == gAgentID) +        { +            mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText")); +        } +        else +        { +            mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText")); +        } +    } +} +  void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)  {  	mProfilePanel = profile_panel; diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 3bb7413ac3..fd7688b99d 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -87,6 +87,7 @@ public:  protected:  	/*virtual*/void updateButtons(); +	void updateNoItemsLabel();  private:  	void onClickDelete(); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 4c539ded38..f13910cde5 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -636,14 +636,17 @@ bool LLScriptEdCore::writeToFile(const std::string& filename)  void LLScriptEdCore::sync()  { -	// Sync with external editor. -	std::string tmp_file = mContainer->getTmpFileName(); -	llstat s; -	if (LLFile::stat(tmp_file, &s) == 0) // file exists -	{ -		if (mLiveFile) mLiveFile->ignoreNextUpdate(); -		writeToFile(tmp_file); -	} +    // Sync with external editor. +    if (mLiveFile) +    { +        std::string tmp_file = mLiveFile->filename(); +        llstat s; +        if (LLFile::stat(tmp_file, &s) == 0) // file exists +        { +            mLiveFile->ignoreNextUpdate(); +            writeToFile(tmp_file); +        } +    }  }  bool LLScriptEdCore::hasChanged() @@ -1027,9 +1030,25 @@ void LLScriptEdCore::openInExternalEditor()  {  	delete mLiveFile; // deletes file -	// Save the script to a temporary file. -	std::string filename = mContainer->getTmpFileName(); -	writeToFile(filename); +	// Generate a suitable filename +    std::string script_name = mScriptName; +    std::string forbidden_chars = "<>:\"\\/|?*"; +    for (std::string::iterator c = forbidden_chars.begin(); c != forbidden_chars.end(); c++) +    { +        script_name.erase(std::remove(script_name.begin(), script_name.end(), *c), script_name.end()); +    } +	std::string filename = mContainer->getTmpFileName(script_name); + +    // Save the script to a temporary file. +    if (!writeToFile(filename)) +    { +        // In case some characters from script name are forbidden +        // and not accounted for, name is too long or some other issue, +        // try file that doesn't include script name +        script_name.clear(); +        filename = mContainer->getTmpFileName(script_name); +        writeToFile(filename); +    }  	// Start watching file changes.  	mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLScriptEdContainer::onExternalChange, mContainer, _1)); @@ -1419,7 +1438,7 @@ LLScriptEdContainer::LLScriptEdContainer(const LLSD& key) :  {  } -std::string LLScriptEdContainer::getTmpFileName() +std::string LLScriptEdContainer::getTmpFileName(const std::string& script_name)  {  	// Take script inventory item id (within the object inventory)  	// to consideration so that it's possible to edit multiple scripts @@ -1431,7 +1450,14 @@ std::string LLScriptEdContainer::getTmpFileName()  	LLMD5 script_id_hash((const U8 *)script_id.c_str());  	script_id_hash.hex_digest(script_id_hash_str); -	return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; +    if (script_name.empty()) +    { +        return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; +    } +    else +    { +        return std::string(LLFile::tmpdir()) + "sl_script_" + script_name + "_" + script_id_hash_str + ".lsl"; +    }  }  bool LLScriptEdContainer::onExternalChange(const std::string& filename) diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 3cf22a0e6e..c1fea31063 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -205,7 +205,7 @@ public:  	LLScriptEdContainer(const LLSD& key, const bool live);  protected: -	std::string		getTmpFileName(); +	std::string		getTmpFileName(const std::string& script_name);  	bool			onExternalChange(const std::string& filename);  	virtual void	saveIfNeeded(bool sync = true) = 0; diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index f325315933..e02b21f036 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -131,7 +131,12 @@ void LLSkinningUtil::initSkinningMatrixPalette(      initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);      for (U32 j = 0; j < count; ++j)      { -        LLJoint *joint = avatar->getJoint(skin->mJointNums[j]); +        S32 joint_num = skin->mJointNums[j]; +        LLJoint *joint = NULL; +        if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS) +        { +            joint = avatar->getJoint(joint_num); +        }          llassert(joint);          if (joint)          { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3fb79e4739..d1c78468b0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1824,9 +1824,6 @@ bool idle_startup()  		display_startup(); -		//all categories loaded. lets create "My Favorites" category -		gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true); -  		// set up callbacks  		LL_INFOS() << "Registering Callbacks" << LL_ENDL;  		LLMessageSystem* msg = gMessageSystem; diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp index 8a5704939a..658ab453d2 100644 --- a/indra/newview/llteleporthistorystorage.cpp +++ b/indra/newview/llteleporthistorystorage.cpp @@ -201,6 +201,12 @@ void LLTeleportHistoryStorage::load()  	std::string line;  	while (std::getline(file, line))  	{ +		if (line.empty()) +		{ +			LL_WARNS() << "Teleport history contains empty line."<< LL_ENDL; +			continue; +		} +		  		LLSD s_item;  		std::istringstream iss(line);  		if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 3fcf193dec..fa2dd60ee0 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -405,7 +405,7 @@ void LLToolMgr::clearTransientTool()  void LLToolMgr::onAppFocusLost()  { -	if (LLApp::isQuitting()) +	if (LLApp::isExiting())  		return;  	if (mSelectedTool) diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 322d0bc727..75a5fabdc2 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1234,7 +1234,8 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l  BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)  { -	if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE; +	static LLCachedControl<bool> show_hover_tips(*LLUI::getInstance()->mSettingGroups["config"], "ShowHoverTips", true); +	if (!show_hover_tips) return TRUE;  	if (!mHoverPick.isValid()) return TRUE;  	LLViewerObject* hover_object = mHoverPick.getObject(); diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index fa3b44f702..553a3cd086 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -144,6 +144,7 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::      httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);      httpOpts->setFollowRedirects(true); +    httpOpts->setSSLVerifyPeer(false);      std::string url = this->getKeyVerificationURL(key);      if (url.empty()) @@ -185,6 +186,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s      httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);      httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); +    httpOpts->setSSLVerifyPeer(false);      std::string url = this->getTranslateURL(fromTo.first, fromTo.second, msg);      if (url.empty()) diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 7842d24279..c1b129750a 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -115,6 +115,7 @@ LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *        mCountSucceeded(0),        mTotalBytesFetched(0)  { +    LLCoprocedureManager::instance().initializePool(VIEWER_ASSET_STORAGE_CORO_POOL);  } @@ -128,6 +129,7 @@ LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *        mCountSucceeded(0),        mTotalBytesFetched(0)  { +    LLCoprocedureManager::instance().initializePool(VIEWER_ASSET_STORAGE_CORO_POOL);  }  LLViewerAssetStorage::~LLViewerAssetStorage() @@ -544,7 +546,7 @@ void LLViewerAssetStorage::assetRequestCoro(      LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts); -    if (LLApp::isQuitting() || !gAssetStorage) +    if (LLApp::isExiting() || !gAssetStorage)      {          // Bail out if result arrives after shutdown has been started.          return; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6d939fbe21..b8bd159ac3 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1498,10 +1498,9 @@ void render_ui_2d()  	if (gSavedSettings.getBOOL("RenderUIBuffer"))  	{ -		LLUI* ui_inst = LLUI::getInstance(); -		if (ui_inst->mDirty) +		if (LLView::sIsRectDirty)  		{ -			ui_inst->mDirty = FALSE; +            LLView::sIsRectDirty = false;  			LLRect t_rect;  			gPipeline.mUIScreen.bindTarget(); @@ -1509,25 +1508,25 @@ void render_ui_2d()  			{  				static const S32 pad = 8; -				ui_inst->mDirtyRect.mLeft -= pad; -				ui_inst->mDirtyRect.mRight += pad; -				ui_inst->mDirtyRect.mBottom -= pad; -				ui_inst->mDirtyRect.mTop += pad; +                LLView::sDirtyRect.mLeft -= pad; +                LLView::sDirtyRect.mRight += pad; +                LLView::sDirtyRect.mBottom -= pad; +                LLView::sDirtyRect.mTop += pad;  				LLGLEnable scissor(GL_SCISSOR_TEST); -				static LLRect last_rect = ui_inst->mDirtyRect; +				static LLRect last_rect = LLView::sDirtyRect;  				//union with last rect to avoid mouse poop -				last_rect.unionWith(ui_inst->mDirtyRect); +				last_rect.unionWith(LLView::sDirtyRect); -				t_rect = ui_inst->mDirtyRect; -				ui_inst->mDirtyRect = last_rect; +				t_rect = LLView::sDirtyRect; +                LLView::sDirtyRect = last_rect;  				last_rect = t_rect; -			 -				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / ui_inst->getScaleFactor().mV[0]); -				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / ui_inst->getScaleFactor().mV[0]); -				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / ui_inst->getScaleFactor().mV[1]); -				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / ui_inst->getScaleFactor().mV[1]); + +				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]); +				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]); +				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]); +				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]);  				LLRect clip_rect(last_rect); @@ -1539,7 +1538,7 @@ void render_ui_2d()  			gPipeline.mUIScreen.flush();  			gGL.setColorMask(true, false); -			ui_inst->mDirtyRect = t_rect; +            LLView::sDirtyRect = t_rect;  		}  		LLGLDisable cull(GL_CULL_FACE); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index afa84a5afc..f770db31dd 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -130,7 +130,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()  	addEntry(LLFolderType::FT_FAVORITE, 			new ViewerFolderEntry("Favorites",				"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));  	addEntry(LLFolderType::FT_CURRENT_OUTFIT, 		new ViewerFolderEntry("Current Outfit",			"Inv_SysOpen",			"Inv_SysClosed",		TRUE,      false)); -	addEntry(LLFolderType::FT_OUTFIT, 				new ViewerFolderEntry("New Outfit",				"Inv_LookFolderOpen",	"Inv_LookFolderClosed",	TRUE,      true)); +	addEntry(LLFolderType::FT_OUTFIT, 				new ViewerFolderEntry("New Outfit",				"Inv_LookFolderOpen",	"Inv_LookFolderClosed",	TRUE,      false));  	addEntry(LLFolderType::FT_MY_OUTFITS, 			new ViewerFolderEntry("My Outfits",				"Inv_SysOpen",			"Inv_SysClosed",		TRUE,      true));  	addEntry(LLFolderType::FT_MESH, 				new ViewerFolderEntry("Meshes",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));  	addEntry(LLFolderType::FT_SETTINGS, 		    new ViewerFolderEntry("Settings",			    "Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true)); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 9ed2df2759..73d0a83a0d 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1237,6 +1237,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 9d05f59b09..c9cca411f3 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -286,6 +286,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*); @@ -2363,6 +2365,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) @@ -4108,25 +4128,31 @@ void near_sit_down_point(BOOL success, void *)  class LLLandSit : public view_listener_t  { -	bool handleEvent(const LLSD& userdata) -	{ -		gAgent.standUp(); -		LLViewerParcelMgr::getInstance()->deselectLand(); +    bool handleEvent(const LLSD& userdata) +    { +        LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; -		LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; -		 -		LLQuaternion target_rot; -		if (isAgentAvatarValid()) -		{ -			target_rot = gAgentAvatarp->getRotation(); -		} -		else -		{ -			target_rot = gAgent.getFrameAgent().getQuaternion(); -		} -		gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f); -		return true; -	} +        LLQuaternion target_rot; +        if (isAgentAvatarValid()) +        { +            target_rot = gAgentAvatarp->getRotation(); +        } +        else +        { +            target_rot = gAgent.getFrameAgent().getQuaternion(); +        } +        gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f); +        return true; +    } +}; + +class LLLandCanSit : public view_listener_t +{ +    bool handleEvent(const LLSD& userdata) +    { +        LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; +        return !posGlobal.isExactlyZero(); // valid position, not beyond draw distance +    }  };  //------------------------------------------------------------------- @@ -8041,6 +8067,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) @@ -9207,6 +9243,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) @@ -9341,6 +9379,7 @@ void initialize_menus()  	// Land pie menu  	view_listener_t::addMenu(new LLLandBuild(), "Land.Build");  	view_listener_t::addMenu(new LLLandSit(), "Land.Sit"); +    view_listener_t::addMenu(new LLLandCanSit(), "Land.CanSit");  	view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");  	view_listener_t::addMenu(new LLLandEdit(), "Land.Edit"); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 2fde4fe49c..7628a6c7ef 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -82,6 +82,8 @@  #include "llcallstack.h"  #include "llsettingsdaycycle.h" +#include <boost/regex.hpp> +  #ifdef LL_WINDOWS  	#pragma warning(disable:4355)  #endif @@ -143,15 +145,22 @@ public:          // build a secondlife://{PLACE} SLurl from this SLapp          std::string url = "secondlife://"; +		boost::regex name_rx("[A-Za-z0-9()_%]+"); +		boost::regex coord_rx("[0-9]+");          for (int i = 0; i < num_params; i++)          {              if (i > 0)              {                  url += "/";              } +			if (!boost::regex_match(params[i].asString(), i > 0 ? coord_rx : name_rx)) +			{ +				return false; +			} +              url += params[i].asString();          } -            +          // Process the SLapp as if it was a secondlife://{PLACE} SLurl          LLURLDispatcher::dispatch(url, "clicked", web, true);          return true; @@ -2241,7 +2250,7 @@ void LLViewerRegion::setSimulatorFeaturesReceived(bool received)  	mSimulatorFeaturesReceived = received;  	if (received)  	{ -		mSimulatorFeaturesReceivedSignal(getRegionID()); +		mSimulatorFeaturesReceivedSignal(getRegionID(), this);  		mSimulatorFeaturesReceivedSignal.disconnect_all_slots();  	}  } @@ -3183,7 +3192,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 dfd8c64f76..fcbf56c81f 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -94,7 +94,7 @@ public:  		NUM_PARTITIONS  	} eObjectPartitions; -	typedef boost::signals2::signal<void(const LLUUID& region_id)> caps_received_signal_t; +	typedef boost::signals2::signal<void(const LLUUID& region_id, LLViewerRegion* regionp)> caps_received_signal_t;  	LLViewerRegion(const U64 &handle,  				   const LLHost &host, diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 21985d5a8a..1d13a306ef 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1928,7 +1928,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)  	if (!LLAppViewer::instance()->restoreErrorTrap())  	{ -		LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL; +        // this always happens, so downgrading it to INFO +		LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL;  	}  	const bool do_not_enforce = false; @@ -2700,7 +2701,7 @@ void LLViewerWindow::draw()  	if (!gSavedSettings.getBOOL("RenderUIBuffer"))  	{ -		LLUI::getInstance()->mDirtyRect = getWindowRectScaled(); +		LLView::sDirtyRect = getWindowRectScaled();  	}  	// HACK for timecode debugging diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f69b9b3861..e085a945a8 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -10584,7 +10584,8 @@ void LLVOAvatar::accountRenderComplexityForObject(                              LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID()                                                     << " total: " << attachment_total_cost                                                     << ", volume: " << attachment_volume_cost -                                                   << ", textures: " << attachment_texture_cost +                                                   << ", " << textures.size() +                                                   << " textures: " << attachment_texture_cost                                                     << ", " << volume->numChildren()                                                     << " children: " << attachment_children_cost                                                     << LL_ENDL; @@ -10684,10 +10685,23 @@ void LLVOAvatar::calculateUpdateRenderComplexity()  			ETextureIndex tex_index = baked_dict->mTextureIndex;  			if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))  			{ -				if (isTextureVisible(tex_index)) -				{ -					cost +=COMPLEXITY_BODY_PART_COST; -				} +                // Same as isTextureVisible(), but doesn't account for isSelf to ensure identical numbers for all avatars +                if (isIndexLocalTexture(tex_index)) +                { +                    if (isTextureDefined(tex_index, 0)) +                    { +                        cost += COMPLEXITY_BODY_PART_COST; +                    } +                } +                else +                { +                    // baked textures can use TE images directly +                    if (isTextureDefined(tex_index) +                        && (getTEImage(tex_index)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)) +                    { +                        cost += COMPLEXITY_BODY_PART_COST; +                    } +                }  			}  		}          LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL; @@ -10728,8 +10742,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()  		// Diagnostic output to identify all avatar-related textures.  		// Does not affect rendering cost calculation. -		// Could be wrapped in a debug option if output becomes problematic. -		if (isSelf()) +		if (isSelf() && debugLoggingEnabled("ARCdetail"))  		{  			// print any attachment textures we didn't already know about.  			for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it) diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 689eeee0e3..5ebc65405f 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -44,6 +44,9 @@ F32 LLVOCacheEntry::sFrontPixelThreshold = 1.0f;  F32 LLVOCacheEntry::sRearPixelThreshold = 1.0f;  BOOL LLVOCachePartition::sNeedsOcclusionCheck = FALSE; +const S32 ENTRY_HEADER_SIZE = 6 * sizeof(S32); +const S32 MAX_ENTRY_BODY_SIZE = 10000; +  BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)   {  	return apr_file->read(src, n_bytes) == n_bytes ; @@ -111,32 +114,22 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)  {  	S32 size = -1;  	BOOL success; +    static U8 data_buffer[ENTRY_HEADER_SIZE];  	mDP.assignBuffer(mBuffer, 0); -	 -	success = check_read(apr_file, &mLocalID, sizeof(U32)); -	if(success) -	{ -		success = check_read(apr_file, &mCRC, sizeof(U32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mHitCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mDupeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mCRCChangeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &size, sizeof(S32)); + +    success = check_read(apr_file, (void *)data_buffer, ENTRY_HEADER_SIZE); +    if (success) +    { +        memcpy(&mLocalID, data_buffer, sizeof(U32)); +        memcpy(&mCRC, data_buffer + sizeof(U32), sizeof(U32)); +        memcpy(&mHitCount, data_buffer + (2 * sizeof(U32)), sizeof(S32)); +        memcpy(&mDupeCount, data_buffer + (3 * sizeof(U32)), sizeof(S32)); +        memcpy(&mCRCChangeCount, data_buffer + (4 * sizeof(U32)), sizeof(S32)); +        memcpy(&size, data_buffer + (5 * sizeof(U32)), sizeof(S32));  		// Corruption in the cache entries -		if ((size > 10000) || (size < 1)) +		if ((size > MAX_ENTRY_BODY_SIZE) || (size < 1))  		{  			// We've got a bogus size, skip reading it.  			// We won't bother seeking, because the rest of this file @@ -345,26 +338,25 @@ void LLVOCacheEntry::dump() const  		<< LL_ENDL;  } -BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const +S32 LLVOCacheEntry::writeToBuffer(U8 *data_buffer) const  { -    static const S32 data_buffer_size = 6 * sizeof(S32); -    static U8 data_buffer[data_buffer_size];      S32 size = mDP.getBufferSize(); +    if (size > MAX_ENTRY_BODY_SIZE) +    { +        LL_WARNS() << "Failed to write entry with size above allowed limit: " << size << LL_ENDL; +        return 0; +    } +      memcpy(data_buffer, &mLocalID, sizeof(U32));      memcpy(data_buffer + sizeof(U32), &mCRC, sizeof(U32));      memcpy(data_buffer + (2 * sizeof(U32)), &mHitCount, sizeof(S32));      memcpy(data_buffer + (3 * sizeof(U32)), &mDupeCount, sizeof(S32));      memcpy(data_buffer + (4 * sizeof(U32)), &mCRCChangeCount, sizeof(S32));      memcpy(data_buffer + (5 * sizeof(U32)), &size, sizeof(S32)); +    memcpy(data_buffer + ENTRY_HEADER_SIZE, (void*)mBuffer, size); -    BOOL success = check_write(apr_file, (void*)data_buffer, data_buffer_size); -    if (success) -    { -        success = check_write(apr_file, (void*)mBuffer, size); -    } - -    return success; +    return ENTRY_HEADER_SIZE + size;  }  //static  @@ -1393,11 +1385,11 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca  	bool success = true ;  	{  		std::string filename; +		LLUUID cache_id;  		getObjectCacheFilename(handle, filename);  		LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); -		LLUUID cache_id ; -		success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ; +		success = check_read(&apr_file, cache_id.mData, UUID_BYTES);  		if(success)  		{		 @@ -1409,7 +1401,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca  			if(success)  			{ -				S32 num_entries; +				S32 num_entries;  // if removal was enabled during write num_entries might be wrong  				success = check_read(&apr_file, &num_entries, sizeof(S32)) ;  				if(success) @@ -1516,28 +1508,57 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:  	{  		std::string filename;  		getObjectCacheFilename(handle, filename); -		LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); +		LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY|APR_TRUNCATE, mLocalAPRFilePoolp); -		success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ; - +		success = check_write(&apr_file, (void*)id.mData, UUID_BYTES);  		if(success)  		{ -			S32 num_entries = cache_entry_map.size() ; +			S32 num_entries = cache_entry_map.size(); // if removal is enabled num_entries might be wrong  			success = check_write(&apr_file, &num_entries, sizeof(S32)); - -			// This can have a lot of entries, so might be better to dump them into buffer first and write in one go. -			for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) -			{ -				if(!removal_enabled || iter->second->isValid()) -				{ -					success = iter->second->writeToFile(&apr_file) ; -					if(!success) -					{ -						break; -					} -				} -			} +            if (success) +            { +                const S32 buffer_size = 32768; //should be large enough for couple MAX_ENTRY_BODY_SIZE +                U8 data_buffer[buffer_size]; // generaly entries are fairly small, so collect them and drop onto disk in one go +                S32 size_in_buffer = 0; + +                // This can have a lot of entries, so might be better to dump them into buffer first and write in one go. +                for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) +                { +                    if (!removal_enabled || iter->second->isValid()) +                    { +                        S32 size = iter->second->writeToBuffer(data_buffer + size_in_buffer); + +                        if (size > ENTRY_HEADER_SIZE) // body is minimum of 1 +                        { +                            size_in_buffer += size; +                        } +                        else +                        { +                            success = false; +                            break; +                        } + +                        // Make sure we have space in buffer for next element +                        if (buffer_size - size_in_buffer < MAX_ENTRY_BODY_SIZE + ENTRY_HEADER_SIZE) +                        { +                            success = check_write(&apr_file, (void*)data_buffer, size_in_buffer); +                            size_in_buffer = 0; +                            if (!success) +                            { +                                break; +                            } +                        } +                    } +                } + +                if (success && size_in_buffer > 0) +                { +                    // final write +                    success = check_write(&apr_file, (void*)data_buffer, size_in_buffer); +                    size_in_buffer = 0; +                } +            }  		}  	} diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 6c95541c11..dd6afd6b85 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -106,7 +106,7 @@ public:  	F32 getSceneContribution() const             { return mSceneContrib;}  	void dump() const; -	BOOL writeToFile(LLAPRFile* apr_file) const; +	S32 writeToBuffer(U8 *data_buffer) const;  	LLDataPackerBinaryBuffer *getDP();  	void recordHit();  	void recordDupe() { mDupeCount++; } diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index b0f57beff8..8dd061728f 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -652,7 +652,6 @@ void LLVivoxVoiceClient::idle(void* user_data)  {  } -  //=========================================================================  // the following are methods to support the coroutine implementation of the   // voice connection and processing.  They should only be called in the context  @@ -684,7 +683,22 @@ void LLVivoxVoiceClient::voiceControlCoro()          bool success = startAndConnectSession();          if (success)          { -            if (mTuningMode) +			// enable/disable the automatic VAD and explicitly set the initial values of  +			// the VAD variables ourselves when it is off - see SL-15072 for more details +			// note: we set the other parameters too even if the auto VAD is on which is ok +			unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto"); +			unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover"); +			unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor"); +			unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity"); +			setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity); +			 +			// watch for changes to the VAD settings via Debug Settings UI and act on them accordingly +			gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this)); +			gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this)); +			gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this)); +			gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this)); + +			if (mTuningMode)              {                  performMicTuning();              } @@ -731,7 +745,6 @@ void LLVivoxVoiceClient::voiceControlCoro()      LL_INFOS("Voice") << "exiting" << LL_ENDL;  } -  bool LLVivoxVoiceClient::startAndConnectSession()  {      bool ok = false; @@ -1326,6 +1339,11 @@ void LLVivoxVoiceClient::logoutOfVivox(bool wait)                  result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult); +                if (sShuttingDown) +                { +                    break; +                } +                  LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;                  // Don't get confused by prior queued events -- note that it's                  // very important that mVivoxPump is an LLEventMailDrop, which @@ -1759,7 +1777,7 @@ bool LLVivoxVoiceClient::waitForChannel()          if (sShuttingDown)          { -            logoutOfVivox(true); +            logoutOfVivox(false);              return false;          } @@ -1851,9 +1869,9 @@ bool LLVivoxVoiceClient::waitForChannel()          mIsProcessingChannels = false; -        logoutOfVivox(true); +        logoutOfVivox(!sShuttingDown /*bool wait*/); -        if (mRelogRequested) +        if (mRelogRequested && !sShuttingDown)          {              LL_DEBUGS("Voice") << "Relog Requested, restarting provisioning" << LL_ENDL;              if (!provisionVoiceAccount()) @@ -3230,6 +3248,73 @@ void LLVivoxVoiceClient::sendLocalAudioUpdates()  	}  } +/** + * Because of the recurring voice cutout issues (SL-15072) we are going to try + * to disable the automatic VAD (Voice Activity Detection) and set the associated + * parameters directly. We will expose them via Debug Settings and that should + * let us iterate on a collection of values that work for us. Hopefully!  + * + * From the VIVOX Docs: + * + * VadAuto: A flag indicating if the automatic VAD is enabled (1) or disabled (0) + * + * VadHangover: The time (in milliseconds) that it takes + * for the VAD to switch back to silence from speech mode after the last speech + * frame has been detected. + * + * VadNoiseFloor: A dimensionless value between 0 and  + * 20000 (default 576) that controls the maximum level at which the noise floor + * may be set at by the VAD's noise tracking. Too low of a value will make noise + * tracking ineffective (A value of 0 disables noise tracking and the VAD then  + * relies purely on the sensitivity property). Too high of a value will make  + * long speech classifiable as noise. + * + * VadSensitivity: A dimensionless value between 0 and  + * 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds + * to decreasing the sensitivity of the VAD (i.e. '0' is most sensitive,  + * while 100 is 'least sensitive') + */ +void LLVivoxVoiceClient::setupVADParams(unsigned int vad_auto, +                                        unsigned int vad_hangover, +                                        unsigned int vad_noise_floor, +                                        unsigned int vad_sensitivity) +{ +    std::ostringstream stream; + +    LL_INFOS("Voice") << "Setting the automatic VAD to " +        << (vad_auto ? "True" : "False") +		<< " and discrete values to" +		<< " VadHangover = " << vad_hangover +		<< ", VadSensitivity = " << vad_sensitivity +		<< ", VadNoiseFloor = " << vad_noise_floor +        << LL_ENDL; + +	// Create a request to set the VAD parameters: +	stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">" +               << "<VadAuto>" << vad_auto << "</VadAuto>" +               << "<VadHangover>" << vad_hangover << "</VadHangover>" +               << "<VadSensitivity>" << vad_sensitivity << "</VadSensitivity>" +               << "<VadNoiseFloor>" << vad_noise_floor << "</VadNoiseFloor>" +           << "</Request>\n\n\n"; + +    if (!stream.str().empty()) +    { +        writeString(stream.str()); +    } +} + +void LLVivoxVoiceClient::onVADSettingsChange() +{ +	// pick up the VAD variables (one of which was changed) +	unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto"); +	unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover"); +	unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor"); +	unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity"); + +	// build a VAD params change request and send it to SLVoice +	setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity); +} +  /////////////////////////////  // Response/Event handlers @@ -7582,6 +7667,18 @@ void LLVivoxProtocolParser::processResponse(std::string tag)  		{  			LLVivoxVoiceClient::getInstance()->accountGetTemplateFontsResponse(statusCode, statusString);  		} +		else if (!stricmp(actionCstr, "Aux.SetVadProperties.1")) +		{ +			// both values of statusCode (old and more recent) indicate valid requests +			if (statusCode != 0 && statusCode != 200) +			{ +				LL_WARNS("Voice") << "Aux.SetVadProperties.1 request failed: " +					<< "statusCode: " << statusCode +					<< " and " +					<< "statusString: " << statusString +					<< LL_ENDL; +			} +		}  		/*  		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))  		 { diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 699c85066b..75ff5429f3 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -446,7 +446,6 @@ protected:  	// local audio updates, mic mute, speaker mute, mic volume and speaker volumes  	void sendLocalAudioUpdates(); -  	/////////////////////////////  	// Response/Event handlers  	void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID); @@ -473,6 +472,12 @@ protected:  	void muteListChanged();  	///////////////////////////// +	// VAD changes +	// disable auto-VAD and configure VAD parameters explicitly +	void setupVADParams(unsigned int vad_auto, unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity); +	void onVADSettingsChange(); + +	/////////////////////////////  	// Sending updates of current state  	void updatePosition(void);  	void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 3bdb8a2981..f063800587 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3987,7 +3987,25 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const  		{  			if (textures.find(img->getID()) == textures.end())  			{ -				S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); +                S32 texture_cost = 0; +                S8 type = img->getType(); +                if (type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE) +                { +                    const LLViewerFetchedTexture* fetched_texturep = static_cast<const LLViewerFetchedTexture*>(img); +                    if (fetched_texturep +                        && fetched_texturep->getFTType() == FTT_LOCAL_FILE +                        && (img->getID() == IMG_ALPHA_GRAD_2D || img->getID() == IMG_ALPHA_GRAD) +                        ) +                    { +                        // These two textures appear to switch between each other, but are of different sizes (4x256 and 256x256). +                        // Hardcode cost from larger one to not cause random complexity changes +                        texture_cost = 320; +                    } +                } +                if (texture_cost == 0) +                { +                    texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); +                }  				textures.insert(texture_cost_t::value_type(img->getID(), texture_cost));  			}  		} @@ -5450,8 +5468,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	U32 useage = group->getSpatialPartition()->mBufferUsage; -	LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); -	LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536); +	static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); +	static LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536);  	U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);  	U32 max_total = (max_node_size * 1024) / LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);  	max_vertices = llmin(max_vertices, (U32) 65535); @@ -6217,7 +6235,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace  #endif  	//calculate maximum number of vertices to store in a single buffer -	LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); +	static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);  	U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);  	max_vertices = llmin(max_vertices, (U32) 65535); diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index 6273f10c69..0aa0280b25 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -31,15 +31,6 @@  const U32 WATCHDOG_SLEEP_TIME_USEC = 1000000; -void default_killer_callback() -{ -#ifdef LL_WINDOWS -	RaiseException(0,0,0,0); -#else -	raise(SIGQUIT); -#endif -} -  // This class runs the watchdog timing thread.  class LLWatchdogTimerThread : public LLThread  { @@ -158,11 +149,10 @@ void LLWatchdogTimeout::ping(const std::string& state)  }  // LLWatchdog -LLWatchdog::LLWatchdog() : -	mSuspectsAccessMutex(), -	mTimer(NULL), -	mLastClockCount(0), -	mKillerCallback(&default_killer_callback) +LLWatchdog::LLWatchdog() +    :mSuspectsAccessMutex() +    ,mTimer(NULL) +	,mLastClockCount(0)  {  } @@ -184,9 +174,8 @@ void LLWatchdog::remove(LLWatchdogEntry* e)  	unlockThread();  } -void LLWatchdog::init(killer_event_callback func) +void LLWatchdog::init()  { -	mKillerCallback = func;  	if(!mSuspectsAccessMutex && !mTimer)  	{  		mSuspectsAccessMutex = new LLMutex(); @@ -253,8 +242,7 @@ void LLWatchdog::run()  				mTimer->stop();  			} -			LL_INFOS() << "Watchdog detected error:" << LL_ENDL; -			mKillerCallback(); +            LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL;  		}  	} diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h index 9a6624258e..ce5cf748f4 100644 --- a/indra/newview/llwatchdog.h +++ b/indra/newview/llwatchdog.h @@ -83,9 +83,7 @@ public:  	void add(LLWatchdogEntry* e);  	void remove(LLWatchdogEntry* e); -	typedef boost::function<void (void)> killer_event_callback; - -	void init(killer_event_callback func = NULL); +	void init();  	void run();  	void cleanup(); @@ -98,8 +96,6 @@ private:  	LLMutex* mSuspectsAccessMutex;  	LLWatchdogTimerThread* mTimer;  	U64 mLastClockCount; - -	killer_event_callback mKillerCallback;  };  #endif // LL_LLTHREADWATCHDOG_H diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 63257d6543..d019b400e8 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -237,7 +237,7 @@ bool LLWeb::useExternalBrowser(const std::string &url)  		up.extractParts();  		std::string uri_string = up.host(); -		boost::regex pattern = boost::regex("\\b(lindenlab.com|secondlife.com)$", boost::regex::perl|boost::regex::icase); +		boost::regex pattern = boost::regex("\\b(lindenlab.com|secondlife.com|secondlife.io)$", boost::regex::perl|boost::regex::icase);  		boost::match_results<std::string::const_iterator> matches;  		return !(boost::regex_search(uri_string, matches, pattern));  	} diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 569f479a16..ff899fe895 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -113,6 +113,7 @@ void LLWebProfile::uploadImageCoro(LLPointer<LLImageFormatted> 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/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 3cc99b28c9..7786ba8a1c 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -626,23 +626,6 @@      top_delta="16"      width="300" /> -  <!-- SL-12594, basic shaders always enabled, no fixed-function GL  -  <check_box -    control_name="VertexShaderEnable" -    height="16" -    initial_value="true" -    label="Basic shaders" -    layout="topleft" -    left="420" -    name="BasicShaders" -    tool_tip="Disabling this option may prevent some graphics card drivers from crashing" -    top_delta="16" -    width="300"> -    <check_box.commit_callback -      function="Pref.VertexShaderEnable" /> -  </check_box> -  --> -        <slider      control_name="RenderTerrainDetail"      follows="left|top" diff --git a/indra/newview/skins/default/xui/en/floater_url_entry.xml b/indra/newview/skins/default/xui/en/floater_url_entry.xml index 29fb29fabf..2dfc0fd125 100644 --- a/indra/newview/skins/default/xui/en/floater_url_entry.xml +++ b/indra/newview/skins/default/xui/en/floater_url_entry.xml @@ -66,7 +66,7 @@       layout="topleft"       left="152"       name="loading_label" -     visible="true"> +     visible="false">          Loading...      </text>  </floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index eda9739976..5a35bbf121 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -152,6 +152,14 @@           parameter="category" />      </menu_item_call>      <menu_item_call +     label="New Outfit" +     layout="topleft" +     name="New Outfit"> +        <menu_item_call.on_click +         function="Inventory.DoCreate" +         parameter="outfit" /> +    </menu_item_call> +    <menu_item_call       label="New Script"       layout="topleft"       name="New Script"> diff --git a/indra/newview/skins/default/xui/en/menu_land.xml b/indra/newview/skins/default/xui/en/menu_land.xml index 2ad5cbbe95..1ce0d65b3e 100644 --- a/indra/newview/skins/default/xui/en/menu_land.xml +++ b/indra/newview/skins/default/xui/en/menu_land.xml @@ -18,6 +18,8 @@      <menu_item_call       label="Sit Here"       name="Sit Here"> +        <menu_item_call.on_enable +         function="Land.CanSit" />          <menu_item_call.on_click           function="Land.Sit" />      </menu_item_call> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0a50ff089f..ceea960e7c 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2442,6 +2442,18 @@ function="World.EnvPreset"                   function="Advanced.ForceErrorSoftwareException" />              </menu_item_call>              <menu_item_call +             label="Force a Crash in a Coroutine" +             name="Force a Crash in a Coroutine"> +                <menu_item_call.on_click +                 function="Advanced.ForceErrorCoroutineCrash" /> +            </menu_item_call> +            <menu_item_call +             label="Force a Crash in a Thread" +             name="Force a Crash in a Thread"> +                <menu_item_call.on_click +                 function="Advanced.ForceErrorThreadCrash" /> +            </menu_item_call> +            <menu_item_call               label="Force Disconnect Viewer"               name="Force Disconnect Viewer">                  <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index cc0dc5c3cc..025027d27d 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10019,6 +10019,15 @@ Removal of the object <nolink>'[OBJ_NAME]'</nolink> from the simulat  Cannot save your selection because you do not have permission to modify the object <nolink>'[OBJ_NAME]'</nolink>.    </notification> + +  <notification +   icon="alertmodal.tga" +   name="NoTransNoSaveToContents" +   type="notify"> +    <tag>fail</tag> +    Cannot save <nolink>'[OBJ_NAME]'</nolink> to object contents because you do not have permission to transfer the object's ownership. +  </notification> +    <notification     icon="alertmodal.tga"     name="NoCopyNoSaveSelection" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index ada980cda1..9023d68ea9 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -35,7 +35,7 @@      </panel.string>    <panel  	 height="18" -	 left="-458" +	 left="-398"  	 top="0"  	 width="120"  	 follows="right|top" @@ -75,7 +75,7 @@    </panel>    <panel      height="18" -    left="-458" +    left="-398"      width="185"      top="1"      follows="right|top"  @@ -142,7 +142,7 @@       left_pad="0"       name="TimeText"       tool_tip="Current time (Pacific)" -     width="145"> +     width="85">          24:00 AM PST      </text>      <icon diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp new file mode 100644 index 0000000000..923bb1e1b2 --- /dev/null +++ b/indra/newview/tests/cppfeatures_test.cpp @@ -0,0 +1,386 @@ +/** + * @file cppfeatures_test + * @author Vir + * @date 2021-03 + * @brief cpp features + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +// Tests related to newer C++ features, for verifying support across compilers and platforms + +#include "linden_common.h" +#include "../test/lltut.h" + +namespace tut +{ + +struct cpp_features_test {}; +typedef test_group<cpp_features_test> cpp_features_test_t; +typedef cpp_features_test_t::object cpp_features_test_object_t; +tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures"); + +// bracket initializers +// Can initialize containers or values using curly brackets +template<> template<> +void cpp_features_test_object_t::test<1>() +{ +	S32 explicit_val{3}; +	ensure(explicit_val==3); + +	S32 default_val{}; +	ensure(default_val==0); +	 +	std::vector<S32> fibs{1,1,2,3,5}; +	ensure(fibs[4]==5); +} + +// auto +// +// https://en.cppreference.com/w/cpp/language/auto +//  +// Can use auto in place of a more complex type specification, if the compiler can infer the type +template<> template<> +void cpp_features_test_object_t::test<2>() +{ +	std::vector<S32> numbers{3,6,9}; + +	// auto element +	auto& aval = numbers[1]; +	ensure("auto element", aval==6); + +	// auto iterator (non-const) +	auto it = numbers.rbegin(); +	*it += 1; +	S32 val = *it; +	ensure("auto iterator", val==10); +} + +// range for +// +// https://en.cppreference.com/w/cpp/language/range-for +// +// Can iterate over containers without explicit iterator +template<> template<> +void cpp_features_test_object_t::test<3>() +{ + +	// Traditional iterator for with container +	// +	// Problems: +	// * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve. +	// * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container. +	std::vector<S32> numbers{3,6,9}; +	for (auto it = numbers.begin(); it != numbers.end(); ++it) +	{ +		auto& n = *it; +		n *= 2; +	} +	ensure("iterator for vector", numbers[2]==18); + +	// Range for with container +	// +	// Under the hood, this is doing the same thing as the traditional +	// for loop above. Still uses begin() and end() but you don't have +	// to access them directly. +	std::vector<S32> numbersb{3,6,9}; +	for (auto& n: numbersb) +	{ +		n *= 2; +	} +	ensure("range for vector", numbersb[2]==18); + +	// Range for over a C-style array. +	// +	// This is handy because the language determines the range automatically. +	// Getting this right manually is a little trickier. +	S32 pows[] = {1,2,4,8,16}; +	S32 sum{}; +	for (const auto& v: pows) +	{ +		sum += v; +	} +	ensure("for C-array", sum==31); +} + +// override specifier +// +// https://en.cppreference.com/w/cpp/language/override +// +// Specify that a particular class function is an override of a virtual function. +// Benefits: +// * Makes code somewhat easier to read by showing intent. +// * Prevents mistakes where you think something is an override but it doesn't actually match the declaration in the parent class. +// Drawbacks: +// * Some compilers require that any class using override must use it consistently for all functions.  +//   This makes switching a class to use override a lot more work.  + +class Foo +{ +public: +	virtual bool is_happy() const = 0; +}; + +class Bar: public Foo +{ +public: +	bool is_happy() const override { return true; }  +	// Override would fail: non-const declaration doesn't match parent  +	// bool is_happy() override { return true; }  +	// Override would fail: wrong name +	// bool is_happx() override { return true; }  +}; + +template<> template<> +void cpp_features_test_object_t::test<4>() +{ +	Bar b; +	ensure("override", b.is_happy()); +} + +// final +// +// https://en.cppreference.com/w/cpp/language/final: "Specifies that a +// virtual function cannot be overridden in a derived class or that a +// class cannot be inherited from." + +class Vehicle +{ +public: +	virtual bool has_wheels() const = 0; +}; + +class WheeledVehicle: public Vehicle +{ +public: +	virtual bool has_wheels() const final override { return true; } +}; + +class Bicycle: public WheeledVehicle +{ +public: +	// Error: can't override final version in WheeledVehicle  +	// virtual bool has_wheels() override const { return true; } +}; + +template<> template<> +void cpp_features_test_object_t::test<5>() +{ +	Bicycle bi; +	ensure("final", bi.has_wheels()); +} + +// deleted function declaration +// +// https://en.cppreference.com/w/cpp/language/function#Deleted_functions +// +// Typical case: copy constructor doesn't make sense for a particular class, so you want to make +// sure the no one tries to copy-construct an instance of the class, and that the +// compiler won't generate a copy constructor for  you automatically. +// Traditional fix is to declare a +// copy constructor but never implement it, giving you a link-time error if anyone tries to use it. +// Now you can explicitly declare a function to be deleted, which has at least two advantages over +// the old way: +// * Makes the intention clear +// * Creates an error sooner, at compile time + +class DoNotCopy +{ +public: +	DoNotCopy() {} +	DoNotCopy(const DoNotCopy& ref) = delete; +}; + +template<> template<> +void cpp_features_test_object_t::test<6>() +{ +	DoNotCopy nc; // OK, default constructor +	//DoNotCopy nc2(nc); // No, can't copy +	//DoNotCopy nc3 = nc; // No, this also calls copy constructor (even though it looks like an assignment) +} + +// defaulted function declaration +// +// https://en.cppreference.com/w/cpp/language/function#Function_definition +// +// What about the complementary case to the deleted function declaration, where you want a copy constructor +// and are happy with the default implementation the compiler will make (memberwise copy). +// Now you can explicitly declare that too. +// Usage: I guess it makes the intent clearer, but otherwise not obviously useful. +class DefaultCopyOK +{ +public: +	DefaultCopyOK(): mVal(123) {} +	DefaultCopyOK(const DefaultCopyOK&) = default; +	S32 val() const { return mVal; } +private: +	S32 mVal; +}; + +template<> template<> +void cpp_features_test_object_t::test<7>() +{ +	DefaultCopyOK d; // OK +	DefaultCopyOK d2(d); // OK +	DefaultCopyOK d3 = d; // OK +	ensure("default copy d", d.val()==123); +	ensure("default copy d2", d.val()==d2.val()); +	ensure("default copy d3", d.val()==d3.val()); +} + +// initialize class members inline +// +// https://en.cppreference.com/w/cpp/language/data_members#Member_initialization +// +// Default class member values can be set where they are declared, using either brackets or = + +// It is preferred to skip creating a constructor if all the work can be done by inline initialization: +// http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html#c45-dont-define-a-default-constructor-that-only-initializes-data-members-use-in-class-member-initializers-instead +// +class InitInline +{ +public: +	S32 mFoo{10}; +}; + +class InitInlineWithConstructor +{ +public: +	// Here mFoo is not specified, so you will get the default value of 10. +	// mBar is specified, so 25 will override the default value. +	InitInlineWithConstructor(): +		mBar(25) +	{} + +	// Default values set using two different styles, same effect. +	S32 mFoo{10}; +	S32 mBar = 20; +}; + +template<> template<> +void cpp_features_test_object_t::test<8>() +{ +	InitInline ii; +	ensure("init member inline 1", ii.mFoo==10); + +	InitInlineWithConstructor iici; +	ensure("init member inline 2", iici.mFoo=10); +	ensure("init member inline 3", iici.mBar==25); +} + +// constexpr +// +// https://en.cppreference.com/w/cpp/language/constexpr +// +// Various things can be computed at compile time, and flagged as constexpr. +constexpr S32 compute2() { return 2; } + +constexpr S32 ce_factorial(S32 n) +{ +	if (n<=0) +	{ +		return 1; +	} +	else +	{ +		return n*ce_factorial(n-1); +	} +} + +template<> template<> +void cpp_features_test_object_t::test<9>() +{ +	S32 val = compute2(); +	ensure("constexpr 1", val==2); + +	// Compile-time factorial. You used to need complex templates to do something this useless. +	S32 fac5 = ce_factorial(5); +	ensure("constexpr 2", fac5==120); +} + +// static assert +// +// https://en.cppreference.com/w/cpp/language/static_assert +// +// You can add asserts to be checked at compile time. The thing to be checked must be a constexpr. +// There are two forms: +// * static_assert(expr); +// * static_assert(expr, message); +// +// Currently only the 2-parameter form works on windows. The 1-parameter form needs a flag we don't set. + +template<> template<> +void cpp_features_test_object_t::test<10>() +{ +	// static_assert(ce_factorial(6)==720); No, needs a flag we don't currently set. +	static_assert(ce_factorial(6)==720, "bad factorial"); // OK +} + +// type aliases +// +// https://en.cppreference.com/w/cpp/language/type_alias +//  +// You can use the "using" statement to create simpler templates that +// are aliases for more complex ones. "Template typedef" + +// This makes stringmap<T> an alias for std::map<std::string, T> +template<typename T> +using stringmap = std::map<std::string, T>; + +template<> template<> +void cpp_features_test_object_t::test<11>() +{ +	stringmap<S32> name_counts{ {"alice", 3}, {"bob", 2} }; +	ensure("type alias", name_counts["bob"]==2); +} + +// Other possibilities: + +// nullptr + +// class enums + +// std::unique_ptr and make_unique + +// std::shared_ptr and make_shared + +// lambdas + +// perfect forwarding + +// variadic templates + +// std::thread + +// std::mutex + +// thread_local + +// rvalue reference && + +// move semantics + +// std::move + +// string_view + +} // namespace tut diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index adac7af712..9f9821b4be 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -683,10 +683,11 @@ class WindowsManifest(ViewerManifest):                  self.path("libvlccore.dll")                  self.path("plugins/") -        # pull in the crash logger from other projects -        # tag:"crash-logger" here as a cue to the exporter -        self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], -                  dst="win_crash_logger.exe") +        if not self.args.get('bugsplat'): # don't include the win_crash_logger if we are using BugSplat +            # pull in the crash logger from other projects +            # tag:"crash-logger" here as a cue to the exporter +            self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], +                      dst="win_crash_logger.exe")          if not self.is_packaging_viewer():              self.package_file = "copied_deps"     @@ -1068,10 +1069,8 @@ class DarwinManifest(ViewerManifest):                  # our apps                  executable_path = {} -                for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"), -                                         # plugin launcher -                                         (os.path.join("llplugin", "slplugin"), "SLPlugin.app"), -                                         ): +                embedded_apps = [ (os.path.join("llplugin", "slplugin"), "SLPlugin.app") ] +                for app_bld_dir, app in embedded_apps:                      self.path2basename(os.path.join(os.pardir,                                                      app_bld_dir, self.args['configuration']),                                         app) diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 87536e146b..251100867f 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -13,7 +13,7 @@ include(LLXML)  include(Linking)  include(Tut)  include(LLAddBuildTest) - +include(bugsplat)  include(GoogleMock)  include_directories( @@ -83,6 +83,10 @@ list(APPEND test_SOURCE_FILES ${test_HEADER_FILES})  add_executable(lltest ${test_SOURCE_FILES}) +if (USE_BUGSPLAT) +  set_target_properties(lltest PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +endif (USE_BUGSPLAT) +  target_link_libraries(lltest      ${LEGACY_STDIO_LIBS}      ${LLDATABASE_LIBRARIES} diff --git a/indra/win_crash_logger/README.txt b/indra/win_crash_logger/README.txt new file mode 100644 index 0000000000..6932a8d9c3 --- /dev/null +++ b/indra/win_crash_logger/README.txt @@ -0,0 +1,3 @@ +This component is no longer used in Linden Lab builds. +Change requests to support continued use by open source +builds are welcome. diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index 267224a79b..0cbe0b0d17 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -498,7 +498,7 @@ bool LLCrashLoggerWindows::frame()  		MSG msg;  		memset(&msg, 0, sizeof(msg)); -		while (!LLApp::isQuitting() && GetMessage(&msg, NULL, 0, 0)) +		while (!LLApp::isExiting() && GetMessage(&msg, NULL, 0, 0))  		{  			TranslateMessage(&msg);  			DispatchMessage(&msg); | 
