diff --git a/doc/contributions.txt b/doc/contributions.txt index 6c39a77dd..258e139bc 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -4,6 +4,10 @@ along with the issue identifier corresponding to the patches we've received from them. To see more about these contributions, visit the browsable version: http://wiki.secondlife.com/wiki/Source_contributions +Entries are related to URLs as follows: +IMP-xxx: http://redmine.kokuaviewer.org/issues/xxx +Everything else ([VWR|SNOW|CT|SVC|WEB]-xxx): https://jira.secondlife.com/browse/KEY-xxx + Able Whitman VWR-650 VWR-1460 @@ -58,12 +62,18 @@ Aimee Trescothick Alejandro Rosenthal VWR-1184 Aleric Inglewood + VWR-10579 (IMP-552) VWR-10759 VWR-10837 VWR-12984 + VWR-13040 (IMP-575) VWR-13996 VWR-14426 VWR-14914 + VWR-24247 + VWR-24312 + VWR-24320 + VWR-24333 SNOW-47 SNOW-84 SNOW-86 @@ -72,18 +82,37 @@ Aleric Inglewood SNOW-129 SNOW-196 SNOW-203 + SNOW-240 SNOW-408 - SNOW-415 + SNOW-415 (IMP-576) + SNOW-477 (IMP-577) SNOW-479 SNOW-626 - SNOW-713 - SNOW-744 - SNOW-751 + SNOW-713 (IMP-692) + SNOW-744 (IMP-578) SNOW-752 SNOW-753 + SNOW-766 (IMP-553) SNOW-772 SNOW-793 + SNOW-796 (IMP-581) + SNOW-800 (IMP-556) SNOW-806 + IMP-429 + IMP-561 + IMP-565 + IMP-566 + IMP-567 + IMP-573 + IMP-590 + IMP-660 + IMP-661 + IMP-662 + IMP-663 + IMP-664 + IMP-670 + IMP-701 + IMP-734 Alissa Sabre VWR-81 VWR-83 @@ -105,7 +134,7 @@ Alissa Sabre VWR-1351 VWR-1353 VWR-1410 - VWR-1843 + VWR-1843 VWR-2116 VWR-2826 VWR-3290 @@ -113,17 +142,17 @@ Alissa Sabre VWR-3857 VWR-4010 VWR-5575 - VWR-5929 - VWR-6384 - VWR-6385 + VWR-5929 + VWR-6384 + VWR-6385 VWR-6386 - VWR-6430 + VWR-6430 VWR-6858 - VWR-6668 - VWR-7086 - VWR-7087 - VWR-7153 - VWR-7168 + VWR-6668 + VWR-7086 + VWR-7087 + VWR-7153 + VWR-7168 VWR-9190 VWR-10728 VWR-12620 @@ -181,6 +210,7 @@ Boroondas Gupte SNOW-201 SNOW-396 SNOW-589 + SNOW-623 (IMP-554) SNOW-624 VWR-233 WEB-262 @@ -549,7 +579,7 @@ Pf Shan CT-321 princess niven VWR-5733 - CT-85 + CT-85 CT-320 CT-352 Renault Clio @@ -590,6 +620,7 @@ Robin Cornelius VWR-11128 VWR-12758 VWR-12686 + VWR-12838 Ryozu Kojima VWR-53 VWR-287 @@ -788,4 +819,3 @@ Zi Ree Zipherius Turas VWR-76 VWR-77 - diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 65dfab0dc..4b2f9dc4b 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -208,10 +208,18 @@ if (LINUX) # this stops us requiring a really recent glibc at runtime add_definitions(-fno-stack-protector) endif (NOT STANDALONE) - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) + if (${ARCH} STREQUAL "x86_64") + add_definitions(-DLINUX64=1 -pipe) + set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + else (${ARCH} STREQUAL "x86_64") + set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) + endif (${ARCH} STREQUAL "x86_64") endif (VIEWER) set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}") @@ -219,6 +227,8 @@ if (LINUX) set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASESSE2 "-O3 ${CMAKE_CXX_FLAGS_RELEASESSE2}") set(CMAKE_C_FLAGS_RELEASESSE2 "-O3 ${CMAKE_C_FLAGS_RELEASESSE2}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO}") endif (LINUX) diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake index 5cd150d58..d1f089891 100644 --- a/indra/cmake/APR.cmake +++ b/indra/cmake/APR.cmake @@ -14,16 +14,18 @@ else (STANDALONE) use_prebuilt_binary(apr_suite) if (WINDOWS) set(APR_LIBRARIES - debug ${ARCH_PREBUILT_DIRS_DEBUG}/apr-1.lib - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apr-1.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.lib + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.lib ) set(APRICONV_LIBRARIES debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapriconv-1.lib optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapriconv-1.lib ) + # Doesn't need to link with iconv.dll + set(APRICONV_LIBRARIES "") set(APRUTIL_LIBRARIES - debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-1.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.lib ${APRICONV_LIBRARIES} + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.lib ${APRICONV_LIBRARIES} ) elseif (DARWIN) set(APR_LIBRARIES @@ -41,9 +43,8 @@ else (STANDALONE) set(APRICONV_LIBRARIES iconv) endif (WINDOWS) set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/apr-1) - set(APRUTIL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/apr-1) if (LINUX AND VIEWER) - list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid) + list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES}) endif (LINUX AND VIEWER) endif (STANDALONE) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 6b9e342f4..b7ec75f54 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -35,7 +35,6 @@ set(cmake_SOURCE_FILES FindNDOF.cmake FindOpenJPEG.cmake FindXmlRpcEpi.cmake - FindMyZLIB.cmake FMOD.cmake FreeType.cmake GStreamer010Plugin.cmake diff --git a/indra/cmake/FindMyZLIB.cmake b/indra/cmake/FindMyZLIB.cmake deleted file mode 100644 index 6d630f1ba..000000000 --- a/indra/cmake/FindMyZLIB.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# -*- cmake -*- - -# - Find zlib -# Find the ZLIB includes and library -# This module defines -# ZLIB_INCLUDE_DIRS, where to find zlib.h, etc. -# ZLIB_LIBRARIES, the libraries needed to use zlib. -# ZLIB_FOUND, If false, do not try to use zlib. -# -# This FindZLIB is about 43 times as fast the one provided with cmake (2.8.x), -# because it doesn't look up the version of zlib, resulting in a dramatic -# speed up for configure (from 4 minutes 22 seconds to 6 seconds). -# -# Note: Since this file is only used for standalone, the windows -# specific parts were left out. - -FIND_PATH(ZLIB_INCLUDE_DIR zlib.h - NO_SYSTEM_ENVIRONMENT_PATH - ) - -FIND_LIBRARY(ZLIB_LIBRARY z) - -if (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) - SET(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) - SET(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) - SET(ZLIB_FOUND "YES") -else (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) - SET(ZLIB_FOUND "NO") -endif (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) - -if (ZLIB_FOUND) - if (NOT ZLIB_FIND_QUIETLY) - message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}") - SET(ZLIB_FIND_QUIETLY TRUE) - endif (NOT ZLIB_FIND_QUIETLY) -else (ZLIB_FOUND) - if (ZLIB_FIND_REQUIRED) - message(FATAL_ERROR "Could not find ZLIB library") - endif (ZLIB_FIND_REQUIRED) -endif (ZLIB_FOUND) - -mark_as_advanced( - ZLIB_LIBRARY - ZLIB_INCLUDE_DIR - ) - diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index a5f957a20..0b483e5cf 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -25,9 +25,11 @@ else (STANDALONE) endif (LINUX) endif (STANDALONE) -#if (GOOGLE_PERFTOOLS_FOUND) -# set(USE_GOOGLE_PERFTOOLS ON CACHE BOOL "Build with Google PerfTools support.") -#endif (GOOGLE_PERFTOOLS_FOUND) +if (GOOGLE_PERFTOOLS_FOUND) + set(USE_GOOGLE_PERFTOOLS ON CACHE BOOL "Build with Google PerfTools support.") +else (GOOGLE_PERFTOOLS_FOUND) + set(USE_GOOGLE_PERFTOOLS OFF) +endif (GOOGLE_PERFTOOLS_FOUND) # XXX Disable temporarily, until we have compilation issues on 64-bit # Etch sorted. @@ -41,7 +43,7 @@ else (USE_GOOGLE_PERFTOOLS) set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) endif (USE_GOOGLE_PERFTOOLS) -if (NOT(DISABLE_TCMALLOC OR USE_GOOGLE_PERFTOOLS)) +if (NOT(DISABLE_TCMALLOC OR NOT USE_GOOGLE_PERFTOOLS)) message(STATUS "Building with Google TCMalloc") set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1_) include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR}) diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index 410766e4f..2862ba7f0 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -7,7 +7,6 @@ include(ZLIB) set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llcommon - ${APRUTIL_INCLUDE_DIR} ${APR_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake index 6dd9c47bd..a91519278 100644 --- a/indra/cmake/Prebuilt.cmake +++ b/indra/cmake/Prebuilt.cmake @@ -1,11 +1,44 @@ # -*- cmake -*- +include(Python) +include(FindSCP) + macro (use_prebuilt_binary _binary) - if(NOT STANDALONE) - get_property(PREBUILT_PACKAGES TARGET prepare PROPERTY PREBUILT) - list(FIND PREBUILT_PACKAGES ${_binary} _index) - if(_index LESS 0) - set_property(TARGET prepare APPEND PROPERTY PREBUILT ${_binary}) - endif(_index LESS 0) - endif(NOT STANDALONE) + if (NOT STANDALONE) + if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed) + if(INSTALL_PROPRIETARY) + include(FindSCP) + if(DEBUG_PREBUILT) + message("cd ${SCRIPTS_DIR} && ${PYTHON_EXECUTABLE} install.py --install-dir=${CMAKE_SOURCE_DIR}/.. --scp=${SCP_EXECUTABLE} ${_binary}") + endif(DEBUG_PREBUILT) + execute_process(COMMAND ${PYTHON_EXECUTABLE} + install.py + --install-dir=${CMAKE_SOURCE_DIR}/.. + --scp=${SCP_EXECUTABLE} + ${_binary} + WORKING_DIRECTORY ${SCRIPTS_DIR} + RESULT_VARIABLE ${_binary}_installed + ) + else(INSTALL_PROPRIETARY) + if(DEBUG_PREBUILT) + message("cd ${SCRIPTS_DIR} && ${PYTHON_EXECUTABLE} install.py --install-dir=${CMAKE_SOURCE_DIR}/.. ${_binary}") + endif(DEBUG_PREBUILT) + execute_process(COMMAND ${PYTHON_EXECUTABLE} + install.py + --install-dir=${CMAKE_SOURCE_DIR}/.. + ${_binary} + WORKING_DIRECTORY ${SCRIPTS_DIR} + RESULT_VARIABLE ${_binary}_installed + ) + endif(INSTALL_PROPRIETARY) + file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}") + else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed) + set(${_binary}_installed 0) + endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed) + if(NOT ${_binary}_installed EQUAL 0) + message(FATAL_ERROR + "Failed to download or unpack prebuilt '${_binary}'." + " Process returned ${${_binary}_installed}.") + endif (NOT ${_binary}_installed EQUAL 0) + endif (NOT STANDALONE) endmacro (use_prebuilt_binary _binary) diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index 6067602d5..64fa85ff2 100644 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -42,6 +42,7 @@ else (STANDALONE) gdk_pixbuf-2.0 Xinerama glib-2.0 + gio-2.0 gmodule-2.0 gobject-2.0 gthread-2.0 diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index 746de0fe9..38d044473 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -2,10 +2,25 @@ include(Prebuilt) if (NOT STANDALONE) + use_prebuilt_binary(libuuid) use_prebuilt_binary(vivox) - if (LINUX) - #use_prebuilt_binary(libuuid) + if(LINUX) + if (${ARCH} STREQUAL "x86_64") + use_prebuilt_binary(32bitcompatibilitylibs) + endif (${ARCH} STREQUAL "x86_64") use_prebuilt_binary(fontconfig) - endif (LINUX) + endif(LINUX) +else (NOT STANDALONE) + # Download there even when using standalone. + set(STANDALONE OFF) + use_prebuilt_binary(vivox) + if(LINUX AND ${ARCH} STREQUAL "x86_64") + use_prebuilt_binary(32bitcompatibilitylibs) + endif(LINUX AND ${ARCH} STREQUAL "x86_64") + set(STANDALONE ON) endif(NOT STANDALONE) +if (WINDOWS) + use_prebuilt_binary(dbghelp) +endif (WINDOWS) + diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake index 44f5619e1..a4befa495 100644 --- a/indra/cmake/WebKitLibPlugin.cmake +++ b/indra/cmake/WebKitLibPlugin.cmake @@ -3,7 +3,29 @@ include(Linking) include(Prebuilt) if (STANDALONE) - find_package(LLQtWebkit REQUIRED) + # The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny. + find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED) + include(${QT_USE_FILE}) + set(QTDIR $ENV{QTDIR}) + if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin") + message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; " + "Qt is found by looking for qmake in your PATH. " + "Please set your PATH such that 'qmake' is found in \$QTDIR/bin, " + "or unset QTDIR if the found Qt is correct.") + endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin") + find_package(LLQtWebkit REQUIRED QUIET) + # Add the plugins. + set(QT_PLUGIN_LIBRARIES) + foreach(qlibname qgif qjpeg) + find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH) + if (QT_PLUGIN_${qlibname}) + list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}}) + else (QT_PLUGIN_${qtlibname}) + message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!") + endif (QT_PLUGIN_${qlibname}) + endforeach(qlibname) + # qjpeg depends on libjpeg + list(APPEND QT_PLUGIN_LIBRARIES jpeg) set(WEBKITLIBPLUGIN OFF CACHE BOOL "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") else (STANDALONE) @@ -32,25 +54,26 @@ if (WINDOWS) elseif (DARWIN) set(WEBKIT_PLUGIN_LIBRARIES optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib - debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/libllqtwebkit.dylib ) elseif (LINUX) - if (STANDALONE) - set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY}) - else (STANDALONE) + if (STANDALONE) + set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES}) + else (STANDALONE) set(WEBKIT_PLUGIN_LIBRARIES - llqtwebkit - qgif - qjpeg - QtWebKit - QtOpenGL - QtNetwork - QtGui - QtCore - fontconfig - X11 - Xrender - GL - ) - endif (STANDALONE) + llqtwebkit + qgif + qjpeg + QtWebKit + QtOpenGL + QtNetwork + QtGui + QtCore + jpeg + fontconfig + X11 + Xrender + GL + ) + endif (STANDALONE) endif (WINDOWS) diff --git a/indra/cmake/ZLIB.cmake b/indra/cmake/ZLIB.cmake index c233b3eec..48e5130ad 100644 --- a/indra/cmake/ZLIB.cmake +++ b/indra/cmake/ZLIB.cmake @@ -6,7 +6,7 @@ set(ZLIB_FIND_REQUIRED ON) include(Prebuilt) if (STANDALONE) - include(FindMyZLIB) + include(FindZLIB) else (STANDALONE) use_prebuilt_binary(zlib) if (WINDOWS) diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index bfac97981..585b47d4a 100644 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -119,6 +119,7 @@ ARGUMENTS=[ Example use: %(name)s --arch=i686 On Linux this would try to use Linux_i686Manifest.""", default=""), + dict(name='artwork', description='Artwork directory.', default=DEFAULT_SRCTREE), dict(name='build', description='Build directory.', default=DEFAULT_SRCTREE), dict(name='buildtype', description="""The build type used. ('Debug', 'Release', 'ReleaseSSE2' or 'RelWithDebInfo') Default is Release """, @@ -126,6 +127,9 @@ ARGUMENTS=[ dict(name='branding_id', description="""Identifier for the branding set to use. Currently, 'secondlife' or 'snowglobe')""", default='secondlife'), + dict(name='channel', + description="""The channel to use for updates, packaging, settings name, etc.""", + default=get_channel), dict(name='configuration', description="""The build configuration used. Only used on OS X for now, but it could be used for other platforms as well.""", @@ -136,16 +140,13 @@ ARGUMENTS=[ though it's not strictly a grid, 'firstlook' is also an acceptable value for this parameter.""", default=""), - dict(name='channel', - description="""The channel to use for updates, packaging, settings name, etc.""", - default=get_channel), - dict(name='login_channel', - description="""The channel to use for login handshake/updates only.""", - default=None), dict(name='installer_name', description=""" The name of the file that the installer should be packaged up into. Only used on Linux at the moment.""", default=None), + dict(name='login_channel', + description="""The channel to use for login handshake/updates only.""", + default=None), dict(name='login_url', description="""The url that the login screen displays in the client.""", default=None), @@ -156,7 +157,9 @@ ARGUMENTS=[ dict(name='source', description='Source directory.', default=DEFAULT_SRCTREE), - dict(name='artwork', description='Artwork directory.', default=DEFAULT_SRCTREE), + dict(name='standalone', + description='Set to ON if this is a standalone build.', + default="OFF"), dict(name='touch', description="""File to touch when action is finished. Touch file will contain the name of the final package in a form suitable diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index ca26d492a..7f352269b 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,6 +13,7 @@ include_directories( ) set(llcommon_SOURCE_FILES + aiaprpool.cpp imageids.cpp indra_constants.cpp llapp.cpp @@ -78,6 +79,8 @@ set(llcommon_SOURCE_FILES set(llcommon_HEADER_FILES CMakeLists.txt + aiaprpool.h + aithreadsafe.h bitpack.h ctype_workaround.h doublelinkedlist.h @@ -155,6 +158,7 @@ set(llcommon_HEADER_FILES llqueuedthread.h llrand.h llrun.h + llscopedvolatileaprpool.h llsd.h llsdserialize.h llsdserialize_xml.h @@ -201,7 +205,7 @@ set_source_files_properties(${llcommon_HEADER_FILES} list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) -add_library (llcommon ${llcommon_SOURCE_FILES}) +add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) add_dependencies(llcommon prepare) target_link_libraries( llcommon diff --git a/indra/llcommon/aiaprpool.cpp b/indra/llcommon/aiaprpool.cpp new file mode 100644 index 000000000..d3748e983 --- /dev/null +++ b/indra/llcommon/aiaprpool.cpp @@ -0,0 +1,198 @@ +/** + * @file aiaprpool.cpp + * + * Copyright (c) 2010, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 04/04/2010 + * - Initial version, written by Aleric Inglewood @ SL + * + * 10/11/2010 + * - Changed filename, class names and license to a more + * company-neutral format. + * - Added APR_HAS_THREADS #if's to allow creation and destruction + * of subpools by threads other than the parent pool owner. + */ + +#include "linden_common.h" + +#include "llerror.h" +#include "aiaprpool.h" +#include "llthread.h" + +// Create a subpool from parent. +void AIAPRPool::create(AIAPRPool& parent) +{ + llassert(!mPool); // Must be non-initialized. + mParent = &parent; + if (!mParent) // Using the default parameter? + { + // By default use the root pool of the current thread. + mParent = &AIThreadLocalData::tldata().mRootPool; + } + llassert(mParent->mPool); // Parent must be initialized. +#if APR_HAS_THREADS + // As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html): + // + // Note that most operations on pools are not thread-safe: a single pool should only be + // accessed by a single thread at any given time. The one exception to this rule is creating + // a subpool of a given pool: one or more threads can safely create subpools at the same + // time that another thread accesses the parent pool. + // + // In other words, it's safe for any thread to create a (sub)pool, independent of who + // owns the parent pool. + mOwner = apr_os_thread_current(); +#else + mOwner = mParent->mOwner; + llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); +#endif + apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool); + llassert_always(apr_pool_create_status == APR_SUCCESS); + llassert(mPool); // Initialized. + apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null); +} + +// Destroy the (sub)pool, if any. +void AIAPRPool::destroy(void) +{ + // Only do anything if we are not already (being) destroyed. + if (mPool) + { +#if !APR_HAS_THREADS + // If we are a root pool, then every thread may destruct us: in that case + // we have to assume that no other thread will use this pool concurrently, + // of course. Otherwise, if we are a subpool, only the thread that owns + // the parent may destruct us, since that is the pool that is still alive, + // possibly being used by others and being altered here. + llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current())); +#endif + apr_pool_t* pool = mPool; + mPool = NULL; // Mark that we are BEING destructed. + apr_pool_cleanup_kill(pool, this, &s_plain_cleanup); + apr_pool_destroy(pool); + } +} + +bool AIAPRPool::parent_is_being_destructed(void) +{ + return mParent && (!mParent->mPool || mParent->parent_is_being_destructed()); +} + +AIAPRInitialization::AIAPRInitialization(void) +{ + static bool apr_initialized = false; + + if (!apr_initialized) + { + apr_initialize(); + } + + apr_initialized = true; +} + +bool AIAPRRootPool::sCountInitialized = false; +apr_uint32_t volatile AIAPRRootPool::sCount; + +extern apr_thread_mutex_t* gLogMutexp; +extern apr_thread_mutex_t* gCallStacksLogMutexp; + +AIAPRRootPool::AIAPRRootPool(void) : AIAPRInitialization(), AIAPRPool(0) +{ + // sCountInitialized don't need locking because when we get here there is still only a single thread. + if (!sCountInitialized) + { + // Initialize the logging mutex + apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool); + apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool); + + apr_status_t status = apr_atomic_init(mPool); + llassert_always(status == APR_SUCCESS); + apr_atomic_set32(&sCount, 1); // Set to 1 to account for the global root pool. + sCountInitialized = true; + + // Initialize thread-local APR pool support. + // Because this recursively calls AIAPRRootPool::AIAPRRootPool(void) + // it must be done last, so that sCount is already initialized. + AIThreadLocalData::init(); + } + apr_atomic_inc32(&sCount); +} + +AIAPRRootPool::~AIAPRRootPool() +{ + if (!apr_atomic_dec32(&sCount)) + { + // The last pool was destructed. Cleanup remainder of APR. + LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; + + if (gLogMutexp) + { + // Clean up the logging mutex + + // All other threads NEED to be done before we clean up APR, so this is okay. + apr_thread_mutex_destroy(gLogMutexp); + gLogMutexp = NULL; + } + if (gCallStacksLogMutexp) + { + // Clean up the logging mutex + + // All other threads NEED to be done before we clean up APR, so this is okay. + apr_thread_mutex_destroy(gCallStacksLogMutexp); + gCallStacksLogMutexp = NULL; + } + + // Must destroy ALL, and therefore this last AIAPRRootPool, before terminating APR. + static_cast(this)->destroy(); + + apr_terminate(); + } +} + +//static +AIAPRRootPool& AIAPRRootPool::get(void) +{ + static AIAPRRootPool global_APRpool(0); // This is what used to be gAPRPoolp. + return global_APRpool; +} + +void AIVolatileAPRPool::clearVolatileAPRPool() +{ + llassert_always(mNumActiveRef > 0); + if (--mNumActiveRef == 0) + { + if (isOld()) + { + destroy(); + mNumTotalRef = 0 ; + } + else + { + // This does not actually free the memory, + // it just allows the pool to re-use this memory for the next allocation. + clear(); + } + } + + // Paranoia check if the pool is jammed. + llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; +} diff --git a/indra/llcommon/aiaprpool.h b/indra/llcommon/aiaprpool.h new file mode 100644 index 000000000..72e9ddbd4 --- /dev/null +++ b/indra/llcommon/aiaprpool.h @@ -0,0 +1,238 @@ +/** + * @file aiaprpool.h + * @brief Implementation of AIAPRPool. + * + * Copyright (c) 2010, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 04/04/2010 + * - Initial version, written by Aleric Inglewood @ SL + * + * 10/11/2010 + * - Changed filename, class names and license to a more + * company-neutral format. + * - Added APR_HAS_THREADS #if's to allow creation and destruction + * of subpools by threads other than the parent pool owner. + */ + +#ifndef AIAPRPOOL_H +#define AIAPRPOOL_H + +#ifdef LL_WINDOWS +#include // Needed before including apr_portable.h +#endif + +#include "apr_portable.h" +#include "apr_pools.h" +#include "llerror.h" + +extern void ll_init_apr(); + +/** + * @brief A wrapper around the APR memory pool API. + * + * Usage of this class should be restricted to passing it to libapr-1 function calls that need it. + * + */ +class LL_COMMON_API AIAPRPool +{ +protected: + apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized. + AIAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero. + apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. + +public: + //! Construct an uninitialized (destructed) pool. + AIAPRPool(void) : mPool(NULL) { } + + //! Construct a subpool from an existing pool. + // This is not a copy-constructor, this class doesn't have one! + AIAPRPool(AIAPRPool& parent) : mPool(NULL) { create(parent); } + + //! Destruct the memory pool (free all of it's subpools and allocated memory). + ~AIAPRPool() { destroy(); } + +protected: + // Create a pool that is allocated from the Operating System. Only used by AIAPRRootPool. + AIAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current()) + { + apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL); + llassert_always(apr_pool_create_status == APR_SUCCESS); + llassert(mPool); + apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null); + } + +public: + //! Create a subpool from parent. May only be called for an uninitialized/destroyed pool. + // The default parameter causes the root pool of the current thread to be used. + void create(AIAPRPool& parent = *static_cast(NULL)); + + //! Destroy the (sub)pool, if any. + void destroy(void); + + // Use some safebool idiom (http://www.artima.com/cppsource/safebool.html) rather than operator bool. + typedef apr_pool_t* const AIAPRPool::* const bool_type; + //! Return true if the pool is initialized. + operator bool_type() const { return mPool ? &AIAPRPool::mPool : 0; } + + // Painful, but we have to either provide access to this, or wrap + // every APR function call that needs a apr_pool_t* to be passed. + // NEVER destroy a pool that is returned by this function! + apr_pool_t* operator()(void) const + { + llassert(mPool); + llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + return mPool; + } + + // Free all memory without destructing the pool. + void clear(void) + { + llassert(mPool); + llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + apr_pool_clear(mPool); + } + +// These methods would make this class 'complete' (as wrapper around the libapr +// pool functions), but we don't use memory pools in the viewer (only when +// we are forced to pass one to a libapr call), so don't define them in order +// not to encourage people to use them. +#if 0 + void* palloc(size_t size) + { + llassert(mPool); + llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + return apr_palloc(mPool, size); + } + void* pcalloc(size_t size) + { + llassert(mPool); + llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + return apr_pcalloc(mPool, size); + } +#endif + +private: + bool parent_is_being_destructed(void); + static apr_status_t s_plain_cleanup(void* userdata) { return static_cast(userdata)->plain_cleanup(); } + + apr_status_t plain_cleanup(void) + { + if (mPool && // We are not being destructed, + parent_is_being_destructed()) // but our parent is. + // This means the pool is being destructed recursively by libapr + // because one of it's parents is being destructed. + { + mPool = NULL; // Stop destroy() from destructing the pool again. + } + return APR_SUCCESS; + } +}; + +class AIAPRInitialization +{ +public: + AIAPRInitialization(void); +}; + +/** + * @brief Root memory pool (allocates memory from the operating system). + * + * This class should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase + * (and LLMutexRootPool when APR_HAS_THREADS isn't defined). + */ +class LL_COMMON_API AIAPRRootPool : public AIAPRInitialization, public AIAPRPool +{ +private: + friend class AIThreadLocalData; + friend class AIThreadSafeSimpleDCRootPool_pbase; +#if !APR_HAS_THREADS + friend class LLMutexRootPool; +#endif + //! Construct a root memory pool. + // Should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase. + AIAPRRootPool(void); + ~AIAPRRootPool(); + +private: + // Keep track of how many root pools exist and when the last one is destructed. + static bool sCountInitialized; + static apr_uint32_t volatile sCount; + +public: + // Return a global root pool that is independent of AIThreadLocalData. + // Normally you should not use this. Only use for early initialization + // (before main) and deinitialization (after main). + static AIAPRRootPool& get(void); + +#if APR_POOL_DEBUG + void grab_ownership(void) + { + // You need a patched libapr to use this. + // See http://web.archiveorange.com/archive/v/5XO9y2zoxUOMt6Gmi1OI + apr_pool_owner_set(mPool); + } +#endif + +private: + // Used for constructing the Special Global Root Pool (returned by AIAPRRootPool::get). + // It is the same as the default constructor but omits to increment sCount. As a result, + // we must be sure that at least one other AIAPRRootPool is created before termination + // of the application (which is the case: we create one AIAPRRootPool per thread). + AIAPRRootPool(int) : AIAPRInitialization(), AIAPRPool(0) { } +}; + +//! Volatile memory pool +// +// 'Volatile' APR memory pool which normally only clears memory, +// and does not destroy the pool (the same pool is reused) for +// greater efficiency. However, as a safe guard the apr pool +// is destructed every FULL_VOLATILE_APR_POOL uses to allow +// the system memory to be allocated more efficiently and not +// get scattered through RAM. +// +class LL_COMMON_API AIVolatileAPRPool : protected AIAPRPool +{ +public: + AIVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { } + + apr_pool_t* getVolatileAPRPool(void) + { + if (!mPool) create(); + ++mNumActiveRef; + ++mNumTotalRef; + return AIAPRPool::operator()(); + } + void clearVolatileAPRPool(void); + + bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; } + bool isUnused() const { return mNumActiveRef == 0; } + +private: + S32 mNumActiveRef; // Number of active uses of the pool. + S32 mNumTotalRef; // Number of total uses of the pool since last creation. + + // Maximum number of references to AIVolatileAPRPool until the pool is recreated. + static S32 const FULL_VOLATILE_APR_POOL = 1024; +}; + +#endif // AIAPRPOOL_H diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h new file mode 100644 index 000000000..70cd2a3db --- /dev/null +++ b/indra/llcommon/aithreadsafe.h @@ -0,0 +1,482 @@ +/** + * @file aithreadsafe.h + * @brief Implementation of AIThreadSafe, AIReadAccessConst, AIReadAccess and AIWriteAccess. + * + * Copyright (c) 2010, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 31/03/2010 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AITHREADSAFE_H +#define AITHREADSAFE_H + +#include + +#include "llthread.h" +#include "llerror.h" + +template struct AIReadAccessConst; +template struct AIReadAccess; +template struct AIWriteAccess; +template struct AIAccess; + +template +class AIThreadSafeBits +{ +private: + // AIThreadSafe is a wrapper around an instance of T. + // Because T might not have a default constructor, it is constructed + // 'in place', with placement new, in the memory reserved here. + // + // Make sure that the memory that T will be placed in is properly + // aligned by using an array of long's. + long mMemory[(sizeof(T) + sizeof(long) - 1) / sizeof(long)]; + +public: + // The wrapped objects are constructed in-place with placement new *outside* + // of this object (by AITHREADSAFE macro(s) or derived classes). + // However, we are responsible for the destruction of the wrapped object. + ~AIThreadSafeBits() { ptr()->~T(); } + + // Only for use by AITHREADSAFE, see below. + void* memory() const { return const_cast(&mMemory[0]); } + +protected: + // Accessors. + T const* ptr() const { return reinterpret_cast(mMemory); } + T* ptr() { return reinterpret_cast(mMemory); } +}; + +/** + * @brief A wrapper class for objects that need to be accessed by more than one thread, allowing concurrent readers. + * + * Use AITHREADSAFE to define instances of any type, and use AIReadAccessConst, + * AIReadAccess and AIWriteAccess to get access to the instance. + * + * For example, + * + * + * class Foo { public: Foo(int, int); }; + * + * AITHREADSAFE(Foo, foo, (2, 3)); + * + * AIReadAccess foo_r(foo); + * // Use foo_r-> for read access. + * + * AIWriteAccess foo_w(foo); + * // Use foo_w-> for write access. + * + * + * If foo is constant, you have to use AIReadAccessConst. + * + * It is possible to pass access objects to a function that + * downgrades the access, for example: + * + * + * void readfunc(AIReadAccess const& access); + * + * AIWriteAccess foo_w(foo); + * readfunc(foo_w); // readfunc will perform read access to foo_w. + * + * + * If AIReadAccess is non-const, you can upgrade the access by creating + * an AIWriteAccess object from it. For example: + * + * + * AIWriteAccess foo_w(foo_r); + * + * + * This API is Robust(tm). If you try anything that could result in problems, + * it simply won't compile. The only mistake you can still easily make is + * to obtain write access to an object when it is not needed, or to unlock + * an object in between accesses while the state of the object should be + * preserved. For example: + * + * + * // This resets foo to point to the first file and then returns that. + * std::string filename = AIWriteAccess(foo)->get_first_filename(); + * + * // WRONG! The state between calling get_first_filename and get_next_filename should be preserved! + * + * AIWriteAccess foo_w(foo); // Wrong. The code below only needs read-access. + * while (!filename.empty()) + * { + * something(filename); + * filename = foo_w->next_filename(); + * } + * + * + * Correct would be + * + * + * AIReadAccess foo_r(foo); + * std::string filename = AIWriteAccess(foo_r)->get_first_filename(); + * while (!filename.empty()) + * { + * something(filename); + * filename = foo_r->next_filename(); + * } + * + * + */ +template +class AIThreadSafe : public AIThreadSafeBits +{ +protected: + // Only these may access the object (through ptr()). + friend struct AIReadAccessConst; + friend struct AIReadAccess; + friend struct AIWriteAccess; + + // Locking control. + AIRWLock mRWLock; + + // For use by AIThreadSafeDC + AIThreadSafe(void) { } + AIThreadSafe(AIAPRPool& parent) : mRWLock(parent) { } + +public: + // Only for use by AITHREADSAFE, see below. + AIThreadSafe(T* object) { llassert(object == AIThreadSafeBits::ptr()); } +}; + +/** + * @brief Instantiate an static, global or local object of a given type wrapped in AIThreadSafe, using an arbitrary constructor. + * + * For example, instead of doing + * + * + * Foo foo(x, y); + * static Bar bar; + * + * + * One can instantiate a thread-safe instance with + * + * + * AITHREADSAFE(Foo, foo, (x, y)); + * static AITHREADSAFE(Bar, bar, ); + * + * + * Note: This macro does not allow to allocate such object on the heap. + * If that is needed, have a look at AIThreadSafeDC. + */ +#define AITHREADSAFE(type, var, paramlist) AIThreadSafe var(new (var.memory()) type paramlist) + +/** + * @brief A wrapper class for objects that need to be accessed by more than one thread. + * + * This class is the same as an AIThreadSafe wrapper, except that it can only + * be used for default constructed objects. + * + * For example, instead of + * + * + * Foo foo; + * + * + * One would use + * + * + * AIThreadSafeDC foo; + * + * + * The advantage over AITHREADSAFE is that this object can be allocated with + * new on the heap. For example: + * + * + * AIThreadSafeDC* ptr = new AIThreadSafeDC; + * + * + * which is not possible with AITHREADSAFE. + */ +template +class AIThreadSafeDC : public AIThreadSafe +{ +public: + // Construct a wrapper around a default constructed object. + AIThreadSafeDC(void) { new (AIThreadSafe::ptr()) T; } +}; + +/** + * @brief Read lock object and provide read access. + */ +template +struct AIReadAccessConst +{ + //! Internal enum for the lock-type of the AI*Access object. + enum state_type + { + readlocked, //!< A AIReadAccessConst or AIReadAccess. + read2writelocked, //!< A AIWriteAccess constructed from a AIReadAccess. + writelocked, //!< A AIWriteAccess constructed from a AIThreadSafe. + write2writelocked //!< A AIWriteAccess constructed from (the AIReadAccess base class of) a AIWriteAccess. + }; + + //! Construct a AIReadAccessConst from a constant AIThreadSafe. + AIReadAccessConst(AIThreadSafe const& wrapper) + : mWrapper(const_cast&>(wrapper)), + mState(readlocked) + { + mWrapper.mRWLock.rdlock(); + } + + //! Destruct the AI*Access object. + // These should never be dynamically allocated, so there is no need to make this virtual. + ~AIReadAccessConst() + { + if (mState == readlocked) + mWrapper.mRWLock.rdunlock(); + else if (mState == writelocked) + mWrapper.mRWLock.wrunlock(); + else if (mState == read2writelocked) + mWrapper.mRWLock.wr2rdlock(); + } + + //! Access the underlaying object for read access. + T const* operator->() const { return mWrapper.ptr(); } + + //! Access the underlaying object for read access. + T const& operator*() const { return *mWrapper.ptr(); } + +protected: + //! Constructor used by AIReadAccess. + AIReadAccessConst(AIThreadSafe& wrapper, state_type state) + : mWrapper(wrapper), mState(state) { } + + AIThreadSafe& mWrapper; //!< Reference to the object that we provide access to. + state_type const mState; //!< The lock state that mWrapper is in. + +private: + // Disallow copy constructing directly. + AIReadAccessConst(AIReadAccessConst const&); +}; + +/** + * @brief Read lock object and provide read access, with possible promotion to write access. + */ +template +struct AIReadAccess : public AIReadAccessConst +{ + typedef typename AIReadAccessConst::state_type state_type; + using AIReadAccessConst::readlocked; + + //! Construct a AIReadAccess from a non-constant AIThreadSafe. + AIReadAccess(AIThreadSafe& wrapper) : AIReadAccessConst(wrapper, readlocked) { this->mWrapper.mRWLock.rdlock(); } + +protected: + //! Constructor used by AIWriteAccess. + AIReadAccess(AIThreadSafe& wrapper, state_type state) : AIReadAccessConst(wrapper, state) { } + + friend class AIWriteAccess; +}; + +/** + * @brief Write lock object and provide read/write access. + */ +template +struct AIWriteAccess : public AIReadAccess +{ + using AIReadAccessConst::readlocked; + using AIReadAccessConst::read2writelocked; + using AIReadAccessConst::writelocked; + using AIReadAccessConst::write2writelocked; + + //! Construct a AIWriteAccess from a non-constant AIThreadSafe. + AIWriteAccess(AIThreadSafe& wrapper) : AIReadAccess(wrapper, writelocked) { this->mWrapper.mRWLock.wrlock();} + + //! Promote read access to write access. + explicit AIWriteAccess(AIReadAccess& access) + : AIReadAccess(access.mWrapper, (access.mState == readlocked) ? read2writelocked : write2writelocked) + { + if (this->mState == read2writelocked) + { + this->mWrapper.mRWLock.rd2wrlock(); + } + } + + //! Access the underlaying object for (read and) write access. + T* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for (read and) write access. + T& operator*() const { return *this->mWrapper.ptr(); } +}; + +/** + * @brief A wrapper class for objects that need to be accessed by more than one thread. + * + * Use AITHREADSAFESIMPLE to define instances of any type, and use AIAccess + * to get access to the instance. + * + * For example, + * + * + * class Foo { public: Foo(int, int); }; + * + * AITHREADSAFESIMPLE(Foo, foo, (2, 3)); + * + * AIAccess foo_w(foo); + * // Use foo_w-> for read and write access. + * + * See also AIThreadSafe + */ +template +class AIThreadSafeSimple : public AIThreadSafeBits +{ +protected: + // Only this one may access the object (through ptr()). + friend struct AIAccess; + + // Locking control. + LLMutex mMutex; + + // For use by AIThreadSafeSimpleDC + AIThreadSafeSimple(void) { } + AIThreadSafeSimple(AIAPRPool& parent) : mMutex(parent) { } + +public: + // Only for use by AITHREADSAFESIMPLE, see below. + AIThreadSafeSimple(T* object) { llassert(object == AIThreadSafeBits::ptr()); } +}; + +/** + * @brief Instantiate an static, global or local object of a given type wrapped in AIThreadSafeSimple, using an arbitrary constructor. + * + * For example, instead of doing + * + * + * Foo foo(x, y); + * static Bar bar; + * + * + * One can instantiate a thread-safe instance with + * + * + * AITHREADSAFESIMPLE(Foo, foo, (x, y)); + * static AITHREADSAFESIMPLE(Bar, bar, ); + * + * + * Note: This macro does not allow to allocate such object on the heap. + * If that is needed, have a look at AIThreadSafeSimpleDC. + */ +#define AITHREADSAFESIMPLE(type, var, paramlist) AIThreadSafeSimple var(new (var.memory()) type paramlist) + +/** + * @brief A wrapper class for objects that need to be accessed by more than one thread. + * + * This class is the same as an AIThreadSafeSimple wrapper, except that it can only + * be used for default constructed objects. + * + * For example, instead of + * + * + * Foo foo; + * + * + * One would use + * + * + * AIThreadSafeSimpleDC foo; + * + * + * The advantage over AITHREADSAFESIMPLE is that this object can be allocated with + * new on the heap. For example: + * + * + * AIThreadSafeSimpleDC* ptr = new AIThreadSafeSimpleDC; + * + * + * which is not possible with AITHREADSAFESIMPLE. + */ +template +class AIThreadSafeSimpleDC : public AIThreadSafeSimple +{ +public: + // Construct a wrapper around a default constructed object. + AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple::ptr()) T; } + +protected: + // For use by AIThreadSafeSimpleDCRootPool + AIThreadSafeSimpleDC(AIAPRPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } +}; + +// Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of +// the root pool before constructing AIThreadSafeSimpleDC. +class AIThreadSafeSimpleDCRootPool_pbase +{ +protected: + AIAPRRootPool mRootPool; + +private: + template friend class AIThreadSafeSimpleDCRootPool; + AIThreadSafeSimpleDCRootPool_pbase(void) { } +}; + +/** + * @brief A wrapper class for objects that need to be accessed by more than one thread. + * + * The same as AIThreadSafeSimpleDC except that this class creates its own AIAPRRootPool + * for the internally used mutexes and condition, instead of using the current threads + * root pool. The advantage of this is that it can be used for objects that need to + * be accessed from the destructors of global objects (after main). The disadvantage + * is that it's less efficient to use your own root pool, therefore it's use should be + * restricted to those cases where it is absolutely necessary. + */ +template +class AIThreadSafeSimpleDCRootPool : private AIThreadSafeSimpleDCRootPool_pbase, public AIThreadSafeSimpleDC +{ +public: + // Construct a wrapper around a default constructed object, using memory allocated + // from the operating system for the internal APR objects (mutexes and conditional), + // as opposed to allocated from the current threads root pool. + AIThreadSafeSimpleDCRootPool(void) : + AIThreadSafeSimpleDCRootPool_pbase(), + AIThreadSafeSimpleDC(mRootPool) { } +}; + +/** + * @brief Write lock object and provide read/write access. + */ +template +struct AIAccess +{ + //! Construct a AIAccess from a non-constant AIThreadSafeSimple. + AIAccess(AIThreadSafeSimple& wrapper) : mWrapper(wrapper) { this->mWrapper.mMutex.lock(); } + + //! Access the underlaying object for (read and) write access. + T* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for (read and) write access. + T& operator*() const { return *this->mWrapper.ptr(); } + + ~AIAccess() { this->mWrapper.mMutex.unlock(); } + +protected: + AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. + +private: + // Disallow copy constructing directly. + AIAccess(AIAccess const&); +}; + +#endif diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index fb2fdd814..3bb833a94 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -95,7 +95,6 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL; LLApp::LLApp() : mThreadErrorp(NULL) { commonCtor(); - startErrorThread(); } void LLApp::commonCtor() @@ -123,13 +122,8 @@ void LLApp::commonCtor() mOptions.append(sd); } - // Make sure we clean up APR when we exit - // Don't need to do this if we're cleaning up APR in the destructor - //atexit(ll_cleanup_apr); - // Set the application to this instance. sApplication = this; - } LLApp::LLApp(LLErrorThread *error_thread) : diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 77cb17c1a..d5cf6ea93 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -256,9 +256,12 @@ protected: */ void stepFrame(); -private: + /** + * @ brief This method is called once as soon as logging is initialized. + */ void startErrorThread(); - + +private: void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions) static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 7210bd2b1..9595707cb 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -34,219 +34,7 @@ #include "linden_common.h" #include "llapr.h" - -apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool -apr_thread_mutex_t *gLogMutexp = NULL; -apr_thread_mutex_t *gCallStacksLogMutexp = NULL; - -const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool - -void ll_init_apr() -{ - if (!gAPRPoolp) - { - // Initialize APR and create the global pool - apr_initialize(); - apr_pool_create(&gAPRPoolp, NULL); - - // Initialize the logging mutex - apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); - apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); - - // Initialize thread-local APR pool support. - LLVolatileAPRPool::initLocalAPRFilePool(); - } -} - - -void ll_cleanup_apr() -{ - LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; - - if (gLogMutexp) - { - // Clean up the logging mutex - - // All other threads NEED to be done before we clean up APR, so this is okay. - apr_thread_mutex_destroy(gLogMutexp); - gLogMutexp = NULL; - } - if (gCallStacksLogMutexp) - { - // Clean up the logging mutex - - // All other threads NEED to be done before we clean up APR, so this is okay. - apr_thread_mutex_destroy(gCallStacksLogMutexp); - gCallStacksLogMutexp = NULL; - } - if (gAPRPoolp) - { - apr_pool_destroy(gAPRPoolp); - gAPRPoolp = NULL; - } - apr_terminate(); -} - -// -// -//LLAPRPool -// -LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) - : mParent(parent), - mReleasePoolFlag(releasePoolFlag), - mMaxSize(size), - mPool(NULL) -{ - createAPRPool() ; -} - -LLAPRPool::~LLAPRPool() -{ - releaseAPRPool() ; -} - -void LLAPRPool::createAPRPool() -{ - if(mPool) - { - return ; - } - - mStatus = apr_pool_create(&mPool, mParent); - ll_apr_warn_status(mStatus) ; - - if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes. - { - apr_allocator_t *allocator = apr_pool_allocator_get(mPool); - if (allocator) - { - apr_allocator_max_free_set(allocator, mMaxSize) ; - } - } -} - -void LLAPRPool::releaseAPRPool() -{ - if(!mPool) - { - return ; - } - - if(!mParent || mReleasePoolFlag) - { - apr_pool_destroy(mPool) ; - mPool = NULL ; - } -} - -apr_pool_t* LLAPRPool::getAPRPool() -{ - if(!mPool) - { - createAPRPool() ; - } - - return mPool ; -} -LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) - : LLAPRPool(parent, size, releasePoolFlag) -{ - mNumActiveRef = 0 ; - mNumTotalRef = 0 ; -} - -apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() -{ - mNumTotalRef++ ; - mNumActiveRef++ ; - return getAPRPool() ; -} - -void LLVolatileAPRPool::clearVolatileAPRPool() -{ - if(mNumActiveRef > 0) - { - mNumActiveRef--; - if(mNumActiveRef < 1) - { - if(isFull()) - { - mNumTotalRef = 0 ; - - //destroy the apr_pool. - releaseAPRPool() ; - } - else - { - //This does not actually free the memory, - //it just allows the pool to re-use this memory for the next allocation. - apr_pool_clear(mPool) ; - } - } - } - else - { - llassert_always(mNumActiveRef > 0) ; - } - - //paranoia check if the pool is jammed. - //will remove the check before going to release. - llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; -} - -BOOL LLVolatileAPRPool::isFull() -{ - return mNumTotalRef > FULL_VOLATILE_APR_POOL ; -} - -#ifdef SHOW_ASSERT -// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread. -static void* gIsMainThread; -bool is_main_thread() { return gIsMainThread == LLVolatileAPRPool::getLocalAPRFilePool(); } -#endif - -// The thread private handle to access the LocalAPRFilePool. -apr_threadkey_t* LLVolatileAPRPool::sLocalAPRFilePoolKey; - -// This should be called exactly once, before the first call to createLocalAPRFilePool. -// static -void LLVolatileAPRPool::initLocalAPRFilePool() -{ - apr_status_t status = apr_threadkey_private_create(&sLocalAPRFilePoolKey, &destroyLocalAPRFilePool, gAPRPoolp); - ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the - // total number of keys per process {PTHREAD_KEYS_MAX} - // has been exceeded. - // Create the thread-local pool for the main thread (this function is called by the main thread). - createLocalAPRFilePool(); -#ifdef SHOW_ASSERT - gIsMainThread = getLocalAPRFilePool(); -#endif -} - -// This should be called once for every thread, before it uses getLocalAPRFilePool. -// static -void LLVolatileAPRPool::createLocalAPRFilePool() -{ - void* thread_local_data = new LLVolatileAPRPool; - apr_status_t status = apr_threadkey_private_set(thread_local_data, sLocalAPRFilePoolKey); - llassert_always(status == APR_SUCCESS); -} - -// This is called once for every thread when the thread is destructed. -// static -void LLVolatileAPRPool::destroyLocalAPRFilePool(void* thread_local_data) -{ - delete reinterpret_cast(thread_local_data); -} - -// static -LLVolatileAPRPool* LLVolatileAPRPool::getLocalAPRFilePool() -{ - void* thread_local_data; - apr_status_t status = apr_threadkey_private_get(&thread_local_data, sLocalAPRFilePoolKey); - llassert_always(status == APR_SUCCESS); - return reinterpret_cast(thread_local_data); -} +#include "llscopedvolatileaprpool.h" //--------------------------------------------------------------------- // @@ -309,13 +97,15 @@ void ll_apr_assert_status(apr_status_t status) // LLAPRFile::LLAPRFile() : mFile(NULL), - mCurrentFilePoolp(NULL) + mVolatileFilePoolp(NULL), + mRegularFilePoolp(NULL) { } LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type) : mFile(NULL), - mCurrentFilePoolp(NULL) + mVolatileFilePoolp(NULL), + mRegularFilePoolp(NULL) { open(filename, flags, access_type); } @@ -334,10 +124,16 @@ apr_status_t LLAPRFile::close() mFile = NULL ; } - if(mCurrentFilePoolp) + if (mVolatileFilePoolp) { - mCurrentFilePoolp->clearVolatileAPRPool() ; - mCurrentFilePoolp = NULL ; + mVolatileFilePoolp->clearVolatileAPRPool() ; + mVolatileFilePoolp = NULL ; + } + + if (mRegularFilePoolp) + { + delete mRegularFilePoolp; + mRegularFilePoolp = NULL; } return ret ; @@ -346,25 +142,28 @@ apr_status_t LLAPRFile::close() apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep) { llassert_always(!mFile); - llassert_always(!mCurrentFilePoolp); + llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp); - // Access the pool and increment it's reference count. - // The reference count of LLVolatileAPRPool objects will be decremented - // again in LLAPRFile::close by calling mCurrentFilePoolp->clearVolatileAPRPool(). - apr_pool_t* pool; - if (access_type == local) + apr_status_t status; { - // Use a "volatile" thread-local pool. - mCurrentFilePoolp = LLVolatileAPRPool::getLocalAPRFilePool(); - pool = mCurrentFilePoolp->getVolatileAPRPool(); + apr_pool_t* apr_file_open_pool; + if (access_type == local) + { + // Use a "volatile" thread-local pool. + mVolatileFilePoolp = &AIThreadLocalData::tldata().mVolatileAPRPool; + // Access the pool and increment it's reference count. + // The reference count of AIVolatileAPRPool objects will be decremented + // again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool(). + apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool(); + } + else + { + mRegularFilePoolp = new AIAPRPool(AIThreadLocalData::tldata().mRootPool); + apr_file_open_pool = (*mRegularFilePoolp)(); + } + status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool); } - else - { - llassert(is_main_thread()); - pool = gAPRPoolp; - } - apr_status_t s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, pool); - if (s != APR_SUCCESS || !mFile) + if (status != APR_SUCCESS || !mFile) { mFile = NULL ; close() ; @@ -372,7 +171,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc { *sizep = 0; } - return s; + return status; } if (sizep) @@ -389,7 +188,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc *sizep = file_size; } - return s; + return status; } // File I/O @@ -449,17 +248,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) //static components of LLAPRFile // -// Used in the static functions below. -class LLScopedVolatileAPRFilePool { -private: - LLVolatileAPRPool* mPool; - apr_pool_t* apr_pool; -public: - LLScopedVolatileAPRFilePool() : mPool(LLVolatileAPRPool::getLocalAPRFilePool()), apr_pool(mPool->getVolatileAPRPool()) { } - ~LLScopedVolatileAPRFilePool() { mPool->clearVolatileAPRPool(); } - operator apr_pool_t*() const { return apr_pool; } -}; - //static S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) { @@ -496,7 +284,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes) { apr_file_t* file_handle; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool); if (s != APR_SUCCESS || !file_handle) { @@ -548,7 +336,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n } apr_file_t* file_handle; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); if (s != APR_SUCCESS || !file_handle) { @@ -593,7 +381,7 @@ bool LLAPRFile::remove(const std::string& filename) { apr_status_t s; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; s = apr_file_remove(filename.c_str(), pool); if (s != APR_SUCCESS) @@ -613,7 +401,7 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname) { apr_status_t s; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; s = apr_file_rename(filename.c_str(), newname.c_str(), pool); if (s != APR_SUCCESS) @@ -631,7 +419,7 @@ bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags) apr_file_t* file_handle; apr_status_t s; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); if (s != APR_SUCCESS || !file_handle) @@ -652,7 +440,7 @@ S32 LLAPRFile::size(const std::string& filename) apr_finfo_t info; apr_status_t s; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); if (s != APR_SUCCESS || !file_handle) @@ -681,7 +469,7 @@ bool LLAPRFile::makeDir(const std::string& dirname) { apr_status_t s; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); if (s != APR_SUCCESS) @@ -698,7 +486,7 @@ bool LLAPRFile::removeDir(const std::string& dirname) { apr_status_t s; - LLScopedVolatileAPRFilePool pool; + LLScopedVolatileAPRPool pool; s = apr_file_remove(dirname.c_str(), pool); if (s != APR_SUCCESS) diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 2aed51511..ded15f531 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -48,73 +48,8 @@ #include "apr_atomic.h" #include "llstring.h" -extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; - -/** - * @brief initialize the common apr constructs -- apr itself, the - * global pool, and a mutex. - */ -void LL_COMMON_API ll_init_apr(); - -/** - * @brief Cleanup those common apr constructs. - */ -void LL_COMMON_API ll_cleanup_apr(); - -// -//LL apr_pool -//manage apr_pool_t, destroy allocated apr_pool in the destruction function. -// -class LL_COMMON_API LLAPRPool -{ -public: - LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ; - ~LLAPRPool() ; - - apr_pool_t* getAPRPool() ; - apr_status_t getStatus() {return mStatus ; } - -protected: - void releaseAPRPool() ; - void createAPRPool() ; - -protected: - apr_pool_t* mPool ; //pointing to an apr_pool - apr_pool_t* mParent ; //parent pool - apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work. - apr_status_t mStatus ; //status when creating the pool - BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true. -}; - -// -//volatile LL apr_pool -//which clears memory automatically. -//so it can not hold static data or data after memory is cleared -// -class LL_COMMON_API LLVolatileAPRPool : protected LLAPRPool -{ -public: - LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); - ~LLVolatileAPRPool(){} - - apr_pool_t* getVolatileAPRPool() ; - - void clearVolatileAPRPool() ; - - BOOL isFull() ; - BOOL isEmpty() {return !mNumActiveRef ;} - - static void initLocalAPRFilePool(); - static void createLocalAPRFilePool(); - static void destroyLocalAPRFilePool(void* thread_local_data); - static LLVolatileAPRPool* getLocalAPRFilePool(); - -private: - S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. - S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. - - static apr_threadkey_t* sLocalAPRFilePoolKey; -} ; +class AIAPRPool; +class AIVolatileAPRPool; /** * @class LLScopedLock @@ -205,7 +140,8 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable // make this non copyable since a copy closes the file private: apr_file_t* mFile ; - LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. + AIVolatileAPRPool* mVolatileFilePoolp; // (Thread local) APR pool currently in use. + AIAPRPool* mRegularFilePoolp; // ...or a regular pool. public: enum access_t { @@ -260,6 +196,4 @@ bool LL_COMMON_API ll_apr_warn_status(apr_status_t status); void LL_COMMON_API ll_apr_assert_status(apr_status_t status); -extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool - #endif // LL_LLAPR_H diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 2cbb71855..298dd4695 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -34,18 +34,10 @@ #include "llcommon.h" #include "llthread.h" -//static -BOOL LLCommon::sAprInitialized = FALSE; - //static void LLCommon::initClass() { LLMemory::initClass(); - if (!sAprInitialized) - { - ll_init_apr(); - sAprInitialized = TRUE; - } LLTimer::initClass(); LLThreadSafeRefCount::initThreadSafeRefCount(); // LLWorkerThread::initClass(); @@ -59,10 +51,5 @@ void LLCommon::cleanupClass() // LLWorkerThread::cleanupClass(); LLThreadSafeRefCount::cleanupThreadSafeRefCount(); LLTimer::cleanupClass(); - if (sAprInitialized) - { - ll_cleanup_apr(); - sAprInitialized = FALSE; - } LLMemory::cleanupClass(); } diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index 851d4ac2d..300ebe2b2 100644 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h @@ -43,8 +43,6 @@ class LL_COMMON_API LLCommon public: static void initClass(); static void cleanupClass(); -private: - static BOOL sAprInitialized; }; #endif diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e549979f0..4cdfe097d 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -55,6 +55,7 @@ #include "llsdserialize.h" #include "llstl.h" #include "lltimer.h" +#include "aithreadsafe.h" extern apr_thread_mutex_t* gCallStacksLogMutexp; @@ -357,12 +358,15 @@ namespace void addCallSite(LLError::CallSite&); void invalidateCallSites(); - static Globals& get(); + static AIThreadSafeSimple& get(); // return the one instance of the globals private: CallSiteVector callSites; + friend class AIThreadSafeSimpleDC; // Calls constructor. + friend class AIThreadSafeSimple; // Calls destructor. + Globals() : messageStreamInUse(false) { } @@ -386,7 +390,7 @@ namespace callSites.clear(); } - Globals& Globals::get() + AIThreadSafeSimple& Globals::get() { /* This pattern, of returning a reference to a static function variable, is to ensure that this global is constructed before @@ -394,8 +398,8 @@ namespace is. See C++ FAQ Lite, sections 10.12 through 10.14 */ - static Globals* globals = new Globals; - return *globals; + static AIThreadSafeSimpleDCRootPool* ts_globals_ptr = new AIThreadSafeSimpleDCRootPool; + return *ts_globals_ptr; } } @@ -424,13 +428,16 @@ namespace LLError int shouldLogCallCounter; - static Settings& get(); + static AIThreadSafeSimple& get(); static void reset(); - static Settings* saveAndReset(); - static void restore(Settings*); + static AIThreadSafeSimple* saveAndReset(); + static void restore(AIThreadSafeSimple*); private: + friend class AIThreadSafeBits; // Calls destructor. + friend class AIThreadSafeSimpleDC; // Calls constructor. + Settings() : printLocation(false), defaultLevel(LLError::LEVEL_DEBUG), @@ -446,53 +453,42 @@ namespace LLError for_each(recorders.begin(), recorders.end(), DeletePointer()); } - - static Settings*& getPtr(); + + static AIThreadSafeSimple* sSettings; }; + + // Pointer to current AIThreadSafeSimple object if any (NULL otherwise). + AIThreadSafeSimple* Settings::sSettings; - Settings& Settings::get() + AIThreadSafeSimple& Settings::get() { - Settings* p = getPtr(); - if (!p) + if (!sSettings) { reset(); - p = getPtr(); } - return *p; + return *sSettings; } void Settings::reset() { - Globals::get().invalidateCallSites(); - - Settings*& p = getPtr(); - delete p; - p = new Settings(); + AIAccess(Globals::get())->invalidateCallSites(); + delete sSettings; + sSettings = new AIThreadSafeSimpleDC; } - Settings* Settings::saveAndReset() + AIThreadSafeSimple* Settings::saveAndReset() { - Globals::get().invalidateCallSites(); - - Settings*& p = getPtr(); - Settings* originalSettings = p; - p = new Settings(); + AIAccess(Globals::get())->invalidateCallSites(); + AIThreadSafeSimple* originalSettings = sSettings; + sSettings = new AIThreadSafeSimpleDC; return originalSettings; } - void Settings::restore(Settings* originalSettings) + void Settings::restore(AIThreadSafeSimple* originalSettings) { - Globals::get().invalidateCallSites(); - - Settings*& p = getPtr(); - delete p; - p = originalSettings; - } - - Settings*& Settings::getPtr() - { - static Settings* currentSettings = NULL; - return currentSettings; + AIAccess(Globals::get())->invalidateCallSites(); + delete sSettings; + sSettings = originalSettings; } } @@ -596,68 +592,64 @@ namespace LLError commonInit(dir); } + void setPrintLocation(AIAccess const& settings_w, bool print) + { + settings_w->printLocation = print; + } + void setPrintLocation(bool print) { - Settings& s = Settings::get(); - s.printLocation = print; + setPrintLocation(AIAccess(Settings::get()), print); } void setFatalFunction(const FatalFunction& f) { - Settings& s = Settings::get(); - s.crashFunction = f; + AIAccess(Settings::get())->crashFunction = f; } FatalFunction getFatalFunction() { - Settings& s = Settings::get(); - return s.crashFunction; + return AIAccess(Settings::get())->crashFunction; } void setTimeFunction(TimeFunction f) { - Settings& s = Settings::get(); - s.timeFunction = f; + AIAccess(Settings::get())->timeFunction = f; + } + + void setDefaultLevel(AIAccess const& settings_w, ELevel level) + { + AIAccess(Globals::get())->invalidateCallSites(); + settings_w->defaultLevel = level; } void setDefaultLevel(ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.defaultLevel = level; + setDefaultLevel(AIAccess(Settings::get()), level); } void setFunctionLevel(const std::string& function_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.functionLevelMap[function_name] = level; + AIAccess(Globals::get())->invalidateCallSites(); + AIAccess(Settings::get())->functionLevelMap[function_name] = level; } void setClassLevel(const std::string& class_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.classLevelMap[class_name] = level; + AIAccess(Globals::get())->invalidateCallSites(); + AIAccess(Settings::get())->classLevelMap[class_name] = level; } void setFileLevel(const std::string& file_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.fileLevelMap[file_name] = level; + AIAccess(Globals::get())->invalidateCallSites(); + AIAccess(Settings::get())->fileLevelMap[file_name] = level; } void setTagLevel(const std::string& tag_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.tagLevelMap[tag_name] = level; + AIAccess(Globals::get())->invalidateCallSites(); + AIAccess(Settings::get())->tagLevelMap[tag_name] = level; } } @@ -701,18 +693,16 @@ namespace LLError { void configure(const LLSD& config) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); + AIAccess settings_w(Settings::get()); + AIAccess(Globals::get())->invalidateCallSites(); + settings_w->functionLevelMap.clear(); + settings_w->classLevelMap.clear(); + settings_w->fileLevelMap.clear(); + settings_w->tagLevelMap.clear(); + settings_w->uniqueLogMessages.clear(); - g.invalidateCallSites(); - s.functionLevelMap.clear(); - s.classLevelMap.clear(); - s.fileLevelMap.clear(); - s.tagLevelMap.clear(); - s.uniqueLogMessages.clear(); - - setPrintLocation(config["print-location"]); - setDefaultLevel(decodeLevel(config["default-level"])); + setPrintLocation(settings_w, config["print-location"]); + setDefaultLevel(settings_w, decodeLevel(config["default-level"])); LLSD sets = config["settings"]; LLSD::array_const_iterator a, end; @@ -722,10 +712,10 @@ namespace LLError ELevel level = decodeLevel(entry["level"]); - setLevels(s.functionLevelMap, entry["functions"], level); - setLevels(s.classLevelMap, entry["classes"], level); - setLevels(s.fileLevelMap, entry["files"], level); - setLevels(s.tagLevelMap, entry["tags"], level); + setLevels(settings_w->functionLevelMap, entry["functions"], level); + setLevels(settings_w->classLevelMap, entry["classes"], level); + setLevels(settings_w->fileLevelMap, entry["files"], level); + setLevels(settings_w->tagLevelMap, entry["tags"], level); } } } @@ -742,26 +732,34 @@ namespace LLError - void addRecorder(Recorder* recorder) + void addRecorder(AIAccess const& settings_w, Recorder* recorder) { if (recorder == NULL) { return; } - Settings& s = Settings::get(); - s.recorders.push_back(recorder); + settings_w->recorders.push_back(recorder); + } + + void addRecorder(Recorder* recorder) + { + addRecorder(AIAccess(Settings::get()), recorder); + } + + void removeRecorder(AIAccess const& settings_w, Recorder* recorder) + { + if (recorder == NULL) + { + return; + } + settings_w->recorders.erase( + std::remove(settings_w->recorders.begin(), settings_w->recorders.end(), recorder), + settings_w->recorders.end()); } void removeRecorder(Recorder* recorder) { - if (recorder == NULL) - { - return; - } - Settings& s = Settings::get(); - s.recorders.erase( - std::remove(s.recorders.begin(), s.recorders.end(), recorder), - s.recorders.end()); + removeRecorder(AIAccess(Settings::get()), recorder); } } @@ -769,12 +767,12 @@ namespace LLError { void logToFile(const std::string& file_name) { - LLError::Settings& s = LLError::Settings::get(); + AIAccess settings_w(Settings::get()); - removeRecorder(s.fileRecorder); - delete s.fileRecorder; - s.fileRecorder = NULL; - s.fileRecorderFileName.clear(); + removeRecorder(settings_w, settings_w->fileRecorder); + delete settings_w->fileRecorder; + settings_w->fileRecorder = NULL; + settings_w->fileRecorderFileName.clear(); if (file_name.empty()) { @@ -788,54 +786,51 @@ namespace LLError return; } - s.fileRecorderFileName = file_name; - s.fileRecorder = f; - addRecorder(f); + settings_w->fileRecorderFileName = file_name; + settings_w->fileRecorder = f; + addRecorder(settings_w, f); } void logToFixedBuffer(LLLineBuffer* fixedBuffer) { - LLError::Settings& s = LLError::Settings::get(); + AIAccess settings_w(Settings::get()); - removeRecorder(s.fixedBufferRecorder); - delete s.fixedBufferRecorder; - s.fixedBufferRecorder = NULL; + removeRecorder(settings_w, settings_w->fixedBufferRecorder); + delete settings_w->fixedBufferRecorder; + settings_w->fixedBufferRecorder = NULL; if (!fixedBuffer) { return; } - s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); - addRecorder(s.fixedBufferRecorder); + settings_w->fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); + addRecorder(settings_w, settings_w->fixedBufferRecorder); } std::string logFileName() { - LLError::Settings& s = LLError::Settings::get(); - return s.fileRecorderFileName; + return AIAccess(Settings::get())->fileRecorderFileName; } } namespace { - void writeToRecorders(LLError::ELevel level, const std::string& message) + void writeToRecorders(AIAccess const& settings_w, LLError::ELevel level, const std::string& message) { - LLError::Settings& s = LLError::Settings::get(); - std::string messageWithTime; - - for (Recorders::const_iterator i = s.recorders.begin(); - i != s.recorders.end(); + + for (Recorders::const_iterator i = settings_w->recorders.begin(); + i != settings_w->recorders.end(); ++i) { LLError::Recorder* r = *i; - if (r->wantsTime() && s.timeFunction != NULL) + if (r->wantsTime() && settings_w->timeFunction != NULL) { if (messageWithTime.empty()) { - messageWithTime = s.timeFunction() + " " + message; + messageWithTime = settings_w->timeFunction() + " " + message; } r->recordMessage(level, messageWithTime); @@ -877,6 +872,9 @@ You get: */ +apr_thread_mutex_t* gLogMutexp; +apr_thread_mutex_t* gCallStacksLogMutexp; + namespace { bool checkLevelMap(const LevelMap& map, const std::string& key, LLError::ELevel& level) @@ -952,10 +950,9 @@ namespace LLError return false; } - Globals& g = Globals::get(); - Settings& s = Settings::get(); + AIAccess settings_w(Settings::get()); - s.shouldLogCallCounter += 1; + settings_w->shouldLogCallCounter += 1; std::string class_name = className(site.mClassInfo); std::string function_name = functionName(site.mFunction); @@ -964,20 +961,20 @@ namespace LLError function_name = class_name + "::" + function_name; } - ELevel compareLevel = s.defaultLevel; + ELevel compareLevel = settings_w->defaultLevel; // The most specific match found will be used as the log level, // since the computation short circuits. // So, in increasing order of importance: // Default < Broad Tag < File < Class < Function < Narrow Tag - ((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false) - || checkLevelMap(s.functionLevelMap, function_name, compareLevel) - || checkLevelMap(s.classLevelMap, class_name, compareLevel) - || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel) - || ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false); + ((site.mNarrowTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mNarrowTag, compareLevel) : false) + || checkLevelMap(settings_w->functionLevelMap, function_name, compareLevel) + || checkLevelMap(settings_w->classLevelMap, class_name, compareLevel) + || checkLevelMap(settings_w->fileLevelMap, abbreviateFile(site.mFile), compareLevel) + || ((site.mBroadTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mBroadTag, compareLevel) : false); site.mCached = true; - g.addCallSite(site); + AIAccess(Globals::get())->addCallSite(site); return site.mShouldLog = site.mLevel >= compareLevel; } @@ -987,16 +984,16 @@ namespace LLError LogLock lock; if (lock.ok()) { - Globals& g = Globals::get(); + AIAccess globals(Globals::get()); - if (!g.messageStreamInUse) + if (!globals->messageStreamInUse) { - g.messageStreamInUse = true; - return &g.messageStream; + globals->messageStreamInUse = true; + return &globals->messageStream; // Returns pointer to member of unlocked object, apparently "protected" by having set globals->messageStreamInUse. } } - return new std::ostringstream; + return new std::ostringstream; // Holy memory leak. } void Log::flush(std::ostringstream* out, char* message) @@ -1017,12 +1014,12 @@ namespace LLError message[127] = '\0' ; } - Globals& g = Globals::get(); - if (out == &g.messageStream) + AIAccess globals(Globals::get()); + if (out == &globals->messageStream) { - g.messageStream.clear(); - g.messageStream.str(""); - g.messageStreamInUse = false; + globals->messageStream.clear(); + globals->messageStream.str(""); + globals->messageStreamInUse = false; } else { @@ -1039,28 +1036,31 @@ namespace LLError return; } - Globals& g = Globals::get(); - Settings& s = Settings::get(); - std::string message = out->str(); - if (out == &g.messageStream) + { - g.messageStream.clear(); - g.messageStream.str(""); - g.messageStreamInUse = false; - } - else - { - delete out; + AIAccess globals(Globals::get()); + if (out == &globals->messageStream) + { + globals->messageStream.clear(); + globals->messageStream.str(""); + globals->messageStreamInUse = false; + } + else + { + delete out; + } } + AIAccess settings_w(Settings::get()); + if (site.mLevel == LEVEL_ERROR) { std::ostringstream fatalMessage; fatalMessage << abbreviateFile(site.mFile) << "(" << site.mLine << ") : error"; - writeToRecorders(site.mLevel, fatalMessage.str()); + writeToRecorders(settings_w, site.mLevel, fatalMessage.str()); } @@ -1075,7 +1075,7 @@ namespace LLError default: prefix << "XXX: "; break; }; - if (s.printLocation) + if (settings_w->printLocation) { prefix << abbreviateFile(site.mFile) << "(" << site.mLine << ") : "; @@ -1093,8 +1093,8 @@ namespace LLError if (site.mPrintOnce) { - std::map::iterator messageIter = s.uniqueLogMessages.find(message); - if (messageIter != s.uniqueLogMessages.end()) + std::map::iterator messageIter = settings_w->uniqueLogMessages.find(message); + if (messageIter != settings_w->uniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; @@ -1110,14 +1110,14 @@ namespace LLError else { prefix << "ONCE: "; - s.uniqueLogMessages[message] = 1; + settings_w->uniqueLogMessages[message] = 1; } } if (site.mPrintOnce) { - std::map::iterator messageIter = s.uniqueLogMessages.find(message); - if (messageIter != s.uniqueLogMessages.end()) + std::map::iterator messageIter = settings_w->uniqueLogMessages.find(message); + if (messageIter != settings_w->uniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; @@ -1133,18 +1133,18 @@ namespace LLError else { prefix << "ONCE: "; - s.uniqueLogMessages[message] = 1; + settings_w->uniqueLogMessages[message] = 1; } } prefix << message; message = prefix.str(); - writeToRecorders(site.mLevel, message); + writeToRecorders(settings_w, site.mLevel, message); - if (site.mLevel == LEVEL_ERROR && s.crashFunction) + if (site.mLevel == LEVEL_ERROR && settings_w->crashFunction) { - s.crashFunction(message); + settings_w->crashFunction(message); } } } @@ -1154,14 +1154,16 @@ namespace LLError namespace LLError { - Settings* saveAndResetSettings() + class ThreadSafeSettings { }; + + ThreadSafeSettings* saveAndResetSettings() { - return Settings::saveAndReset(); + return reinterpret_cast(Settings::saveAndReset()); } - void restoreSettings(Settings* s) + void restoreSettings(ThreadSafeSettings* s) { - return Settings::restore(s); + Settings::restore(reinterpret_cast*>(s)); } std::string removePrefix(std::string& s, const std::string& p) @@ -1207,8 +1209,7 @@ namespace LLError int shouldLogCallCount() { - Settings& s = Settings::get(); - return s.shouldLogCallCounter; + return AIAccess(Settings::get())->shouldLogCallCounter; } #if LL_WINDOWS diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 2a7c500db..c6eb39cae 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -167,9 +167,9 @@ namespace LLError Utilities for use by the unit tests of LLError itself. */ - class Settings; - LL_COMMON_API Settings* saveAndResetSettings(); - LL_COMMON_API void restoreSettings(Settings *); + class ThreadSafeSettings; + LL_COMMON_API ThreadSafeSettings* saveAndResetSettings(); + LL_COMMON_API void restoreSettings(ThreadSafeSettings *); LL_COMMON_API std::string abbreviateFile(const std::string& filePath); LL_COMMON_API int shouldLogCallCount(); diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp index 1f6a06c24..08be3e259 100644 --- a/indra/llcommon/llfixedbuffer.cpp +++ b/indra/llcommon/llfixedbuffer.cpp @@ -36,8 +36,7 @@ LLFixedBuffer::LLFixedBuffer(const U32 max_lines) : LLLineBuffer(), - mMaxLines(max_lines), - mMutex(NULL) + mMaxLines(max_lines) { mTimer.reset(); } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 39a745f25..df49757a6 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -107,17 +107,7 @@ #endif -// Static linking with apr on windows needs to be declared. -#ifdef LL_WINDOWS -#ifndef APR_DECLARE_STATIC -#define APR_DECLARE_STATIC // For APR on Windows -#endif -#ifndef APU_DECLARE_STATIC -#define APU_DECLARE_STATIC // For APR util on Windows -#endif -#endif - -// Deal with the differeneces on Windows +// Deal with the differences on Windows #if defined(LL_WINDOWS) #define BOOST_REGEX_NO_LIB 1 #define CURL_STATICLIB 1 @@ -169,7 +159,6 @@ #define LL_DLLIMPORT #endif // LL_WINDOWS -/* #ifdef llcommon_EXPORTS // Compiling llcommon (shared) #define LL_COMMON_API LL_DLLEXPORT @@ -177,9 +166,5 @@ // Using llcommon (shared) #define LL_COMMON_API LL_DLLIMPORT #endif // llcommon_EXPORTS -*/ - -//I hate DLLs -SG -#define LL_COMMON_API #endif // not LL_LINDEN_PREPROCESSOR_H diff --git a/indra/llcommon/llscopedvolatileaprpool.h b/indra/llcommon/llscopedvolatileaprpool.h new file mode 100644 index 000000000..724dc7f05 --- /dev/null +++ b/indra/llcommon/llscopedvolatileaprpool.h @@ -0,0 +1,58 @@ +/** + * @file llscopedvolatileaprpool.h + * @brief Implementation of LLScopedVolatileAPRPool + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H +#define LL_LLSCOPEDVOLATILEAPRPOOL_H + +#include "llthread.h" + +//! Scoped volatile memory pool. +// +// As the AIVolatileAPRPool should never keep allocations very +// long, it's most common use is for allocations with a lifetime +// equal to it's scope. +// +// This is a convenience class that makes just a little easier to type. +// +class LLScopedVolatileAPRPool +{ +private: + AIVolatileAPRPool& mPool; + apr_pool_t* mScopedAPRpool; +public: + LLScopedVolatileAPRPool() : mPool(AIThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { } + ~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); } + // Only use this to pass the pointer to a libapr-1 function that requires it. + operator apr_pool_t*() const { return mScopedAPRpool; } +}; + +#endif diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 6b1115a54..171747921 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -36,6 +36,7 @@ #include #include #include +#include #if LL_LINUX || LL_SOLARIS #include @@ -212,7 +213,7 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static std::basic_string null; + static std::basic_string const null; typedef std::map format_map_t; static S32 format(std::basic_string& s, const format_map_t& fmt_map); @@ -303,7 +304,7 @@ public: }; -template std::basic_string LLStringUtilBase::null; +template std::basic_string const LLStringUtilBase::null; typedef LLStringUtilBase LLStringUtil; typedef LLStringUtilBase LLWStringUtil; diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 9b74e1d1d..7ced30939 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -72,8 +72,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // Set thread state to running threadp->mStatus = RUNNING; - // Create a thread local APRFile pool. - LLVolatileAPRPool::createLocalAPRFilePool(); + // Create a thread local data. + AIThreadLocalData::create(threadp); // Run the user supplied function threadp->run(); @@ -87,24 +87,14 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap } -LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : +LLThread::LLThread(std::string const& name) : mPaused(FALSE), mName(name), mAPRThreadp(NULL), - mStatus(STOPPED) + mStatus(STOPPED), + mThreadLocalData(NULL) { - // Thread creation probably CAN be paranoid about APR being initialized, if necessary - if (poolp) - { - mIsLocalPool = FALSE; - mAPRPoolp = poolp; - } - else - { - mIsLocalPool = TRUE; - apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread - } - mRunCondition = new LLCondition(mAPRPoolp); + mRunCondition = new LLCondition; } @@ -147,24 +137,18 @@ void LLThread::shutdown() if (!isStopped()) { // This thread just wouldn't stop, even though we gave it time - llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl; + llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl; return; } mAPRThreadp = NULL; } delete mRunCondition; - - if (mIsLocalPool) - { - apr_pool_destroy(mAPRPoolp); - } } - void LLThread::start() { - apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); + apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); // We won't bother joining apr_thread_detach(mAPRThreadp); @@ -265,38 +249,72 @@ void LLThread::wakeLocked() } } +#ifdef SHOW_ASSERT +// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread. +static apr_os_thread_t main_thread_id; +LL_COMMON_API bool is_main_thread() { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); } +#endif + +// The thread private handle to access the AIThreadLocalData instance. +apr_threadkey_t* AIThreadLocalData::sThreadLocalDataKey; + +//static +void AIThreadLocalData::init(void) +{ + // Only do this once. + if (sThreadLocalDataKey) + { + return; + } + + apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &AIThreadLocalData::destroy, AIAPRRootPool::get()()); + ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the + // total number of keys per process {PTHREAD_KEYS_MAX} + // has been exceeded. + + // Create the thread-local data for the main thread (this function is called by the main thread). + AIThreadLocalData::create(NULL); + +#ifdef SHOW_ASSERT + // This function is called by the main thread. + main_thread_id = apr_os_thread_current(); +#endif +} + +// This is called once for every thread when the thread is destructed. +//static +void AIThreadLocalData::destroy(void* thread_local_data) +{ + delete reinterpret_cast(thread_local_data); +} + +//static +void AIThreadLocalData::create(LLThread* threadp) +{ + AIThreadLocalData* new_tld = new AIThreadLocalData; + if (threadp) + { + threadp->mThreadLocalData = new_tld; + } + apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey); + llassert_always(status == APR_SUCCESS); +} + +//static +AIThreadLocalData& AIThreadLocalData::tldata(void) +{ + if (!sThreadLocalDataKey) + AIThreadLocalData::init(); + + void* data; + apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey); + llassert_always(status == APR_SUCCESS); + return *static_cast(data); +} + //============================================================================ -LLMutex::LLMutex(apr_pool_t *poolp) : - mAPRMutexp(NULL) -{ - //if (poolp) - //{ - // mIsLocalPool = FALSE; - // mAPRPoolp = poolp; - //} - //else - { - mIsLocalPool = TRUE; - apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread - } - apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); -} - -LLMutex::~LLMutex() -{ -#if _DEBUG - llassert(!isLocked()); // better not be locked! -#endif - apr_thread_mutex_destroy(mAPRMutexp); - mAPRMutexp = NULL; - if (mIsLocalPool) - { - apr_pool_destroy(mAPRPoolp); - } -} - -bool LLMutex::isLocked() +bool LLMutexBase::isLocked() { if (!tryLock()) { @@ -308,12 +326,9 @@ bool LLMutex::isLocked() //============================================================================ -LLCondition::LLCondition(apr_pool_t *poolp) : - LLMutex(poolp) +LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent) { - // base class (LLMutex) has already ensured that mAPRPoolp is set up. - - apr_thread_cond_create(&mAPRCondp, mAPRPoolp); + apr_thread_cond_create(&mAPRCondp, mPool()); } LLCondition::~LLCondition() @@ -349,7 +364,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount() { if (!sMutex) { - sMutex = new LLMutex(0); + sMutex = new LLMutex; } } diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 399f0f741..2146216aa 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -38,11 +38,32 @@ #include "llmemory.h" #include "apr_thread_cond.h" +#include "aiaprpool.h" + +#ifdef SHOW_ASSERT +extern bool is_main_thread(void); +#endif class LLThread; class LLMutex; class LLCondition; +class LL_COMMON_API AIThreadLocalData +{ +private: + static apr_threadkey_t* sThreadLocalDataKey; + +public: + // Thread-local memory pool. + AIAPRRootPool mRootPool; + AIVolatileAPRPool mVolatileAPRPool; + + static void init(void); + static void destroy(void* thread_local_data); + static void create(LLThread* pthread); + static AIThreadLocalData& tldata(void); +}; + class LL_COMMON_API LLThread { public: @@ -53,7 +74,7 @@ public: QUITTING= 2 // Someone wants this thread to quit } EThreadStatus; - LLThread(const std::string& name, apr_pool_t *poolp = NULL); + LLThread(std::string const& name); virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. virtual void shutdown(); // stops the thread @@ -82,7 +103,8 @@ public: // this kicks off the apr thread void start(void); - apr_pool_t *getAPRPool() { return mAPRPoolp; } + // Return thread-local data for the current thread. + static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); } private: BOOL mPaused; @@ -95,10 +117,11 @@ protected: LLCondition* mRunCondition; apr_thread_t *mAPRThreadp; - apr_pool_t *mAPRPoolp; - BOOL mIsLocalPool; EThreadStatus mStatus; + friend void AIThreadLocalData::create(LLThread* threadp); + AIThreadLocalData* mThreadLocalData; + void setQuitting(); // virtual function overridden by subclass -- this will be called when the thread runs @@ -125,12 +148,9 @@ protected: //============================================================================ -class LL_COMMON_API LLMutex +class LL_COMMON_API LLMutexBase { public: - LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex - ~LLMutex(); - void lock() { apr_thread_mutex_lock(mAPRMutexp); } void unlock() { apr_thread_mutex_unlock(mAPRMutexp); } // Returns true if lock was obtained successfully. @@ -139,16 +159,60 @@ public: bool isLocked(); // non-blocking, but does do a lock/unlock so not free protected: - apr_thread_mutex_t *mAPRMutexp; - apr_pool_t *mAPRPoolp; - BOOL mIsLocalPool; + // mAPRMutexp is initialized and uninitialized in the derived class. + apr_thread_mutex_t* mAPRMutexp; }; +class LL_COMMON_API LLMutex : public LLMutexBase +{ +public: + LLMutex(AIAPRPool& parent = LLThread::tldata().mRootPool) : mPool(parent) + { + apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mPool()); + } + ~LLMutex() + { + llassert(!isLocked()); // better not be locked! + apr_thread_mutex_destroy(mAPRMutexp); + mAPRMutexp = NULL; + } + +protected: + AIAPRPool mPool; +}; + +#if APR_HAS_THREADS +// No need to use a root pool in this case. +typedef LLMutex LLMutexRootPool; +#else // APR_HAS_THREADS +class LL_COMMON_API LLMutexRootPool : public LLMutexBase +{ +public: + LLMutexRootPool(void) + { + apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mRootPool()); + } + ~LLMutexRootPool() + { +#if APR_POOL_DEBUG + // It is allowed to destruct root pools from a different thread. + mRootPool.grab_ownership(); +#endif + llassert(!isLocked()); // better not be locked! + apr_thread_mutex_destroy(mAPRMutexp); + mAPRMutexp = NULL; + } + +protected: + AIAPRRootPool mRootPool; +}; +#endif // APR_HAS_THREADS + // Actually a condition/mutex pair (since each condition needs to be associated with a mutex). class LL_COMMON_API LLCondition : public LLMutex { public: - LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well. + LLCondition(AIAPRPool& parent = LLThread::tldata().mRootPool); ~LLCondition(); void wait(); // blocks @@ -162,7 +226,7 @@ protected: class LL_COMMON_API LLMutexLock { public: - LLMutexLock(LLMutex* mutex) + LLMutexLock(LLMutexBase* mutex) { mMutex = mutex; mMutex->lock(); @@ -172,7 +236,102 @@ public: mMutex->unlock(); } private: - LLMutex* mMutex; + LLMutexBase* mMutex; +}; + +class AIRWLock +{ +public: + AIRWLock(AIAPRPool& parent = LLThread::tldata().mRootPool) : + mWriterWaitingMutex(parent), mNoHoldersCondition(parent), mHoldersCount(0), mWriterIsWaiting(false) { } + +private: + LLMutex mWriterWaitingMutex; //!< This mutex is locked while some writer is waiting for access. + LLCondition mNoHoldersCondition; //!< Access control for mHoldersCount. Condition true when there are no more holders. + int mHoldersCount; //!< Number of readers or -1 if a writer locked this object. + // This is volatile because we read it outside the critical area of mWriterWaitingMutex, at [1]. + // That means that other threads can change it while we are already in the (inlined) function rdlock. + // Without volatile, the following assembly would fail: + // register x = mWriterIsWaiting; + // /* some thread changes mWriterIsWaiting */ + // if (x ... + // However, because the function is fuzzy to begin with (we don't mind that this race + // condition exists) it would work fine without volatile. So, basically it's just here + // out of principle ;). -- Aleric + bool volatile mWriterIsWaiting; //!< True when there is a writer waiting for write access. + +public: + void rdlock(bool high_priority = false) + { + // Give a writer a higher priority (kinda fuzzy). + if (mWriterIsWaiting && !high_priority) // [1] If there is a writer interested, + { + mWriterWaitingMutex.lock(); // [2] then give it precedence and wait here. + // If we get here then the writer got it's access; mHoldersCount == -1. + mWriterWaitingMutex.unlock(); + } + mNoHoldersCondition.lock(); // [3] Get exclusive access to mHoldersCount. + while (mHoldersCount == -1) // [4] + { + mNoHoldersCondition.wait(); // [5] Wait till mHoldersCount is (or just was) 0. + } + ++mHoldersCount; // One more reader. + mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. + } + void rdunlock(void) + { + mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. + if (--mHoldersCount == 0) // Was this the last reader? + { + mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7]. + } + mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. + } + void wrlock(void) + { + mWriterWaitingMutex.lock(); // Block new readers, see [2], + mWriterIsWaiting = true; // from this moment on, see [1]. + mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. + while (mHoldersCount != 0) // Other readers or writers have this lock? + { + mNoHoldersCondition.wait(); // [6] Wait till mHoldersCount is (or just was) 0. + } + mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1]. + mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3]. + mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]). + mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]). + } + void wrunlock(void) + { + mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. + mHoldersCount = 0; // We have no writer anymore. + mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7]. + mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. + } + void rd2wrlock(void) + { + mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. Blocks new readers at [3]. + if (--mHoldersCount > 0) // Any other reads left? + { + mWriterWaitingMutex.lock(); // Block new readers, see [2], + mWriterIsWaiting = true; // from this moment on, see [1]. + while (mHoldersCount != 0) // Other readers (still) have this lock? + { + mNoHoldersCondition.wait(); // [7] Wait till mHoldersCount is (or just was) 0. + } + mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1]. + mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3]. + } + mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]). + mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]). + } + void wr2rdlock(void) + { + mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. + mHoldersCount = 1; // Turn writer into a reader. + mNoHoldersCondition.signal(); // Tell waiting readers, see [5]. + mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. + } }; //============================================================================ @@ -187,7 +346,6 @@ void LLThread::unlockData() mRunCondition->unlock(); } - //============================================================================ // see llmemory.h for LLPointer<> definition diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index c4be02818..65f27095b 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -43,7 +43,7 @@ LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : LLQueuedThread(name, threaded) { - mDeleteMutex = new LLMutex(NULL); + mDeleteMutex = new LLMutex; } LLWorkerThread::~LLWorkerThread() @@ -205,7 +205,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na mRequestPriority(LLWorkerThread::PRIORITY_NORMAL), mWorkerClassName(name), mRequestHandle(LLWorkerThread::nullHandle()), - mMutex(NULL), mWorkFlags(0) { if (!mWorkerThread) diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index 3d761dc87..117dc05cc 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -200,7 +200,7 @@ protected: U32 mRequestPriority; // last priority set private: - LLMutex mMutex; + LLMutexRootPool mMutex; // Use LLMutexRootPool since this object is created and destructed by multiple threads. LLAtomicU32 mWorkFlags; }; diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp old mode 100755 new mode 100644 index 804c51274..3dc41e897 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -387,8 +387,7 @@ bool LLCrashLogger::init() return false; } - gServicePump = new LLPumpIO(gAPRPoolp); - gServicePump->prime(gAPRPoolp); + gServicePump = new LLPumpIO; LLHTTPClient::setPump(*gServicePump); //If we've opened the crash logger, assume we can delete the marker file if it exists diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h old mode 100755 new mode 100644 diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 546a16d16..3f3dbc87c 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -57,7 +57,7 @@ LLMutex* LLImage::sMutex = NULL; //static void LLImage::initClass() { - sMutex = new LLMutex(NULL); + sMutex = new LLMutex; LLImageJ2C::openDSO(); } diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index fbfb91697..e01e3adce 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -47,7 +47,7 @@ typedef const char* (*EngineInfoLLImageJ2CFunction)(); CreateLLImageJ2CFunction j2cimpl_create_func; DestroyLLImageJ2CFunction j2cimpl_destroy_func; EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func; -apr_pool_t *j2cimpl_dso_memory_pool; +AIAPRPool j2cimpl_dso_memory_pool; apr_dso_handle_t *j2cimpl_dso_handle; //Declare the prototype for theses functions here, their functionality @@ -82,13 +82,12 @@ void LLImageJ2C::openDSO() gDirUtilp->getExecutableDir()); j2cimpl_dso_handle = NULL; - j2cimpl_dso_memory_pool = NULL; + j2cimpl_dso_memory_pool.create(); //attempt to load the shared library - apr_pool_create(&j2cimpl_dso_memory_pool, NULL); rv = apr_dso_load(&j2cimpl_dso_handle, dso_path.c_str(), - j2cimpl_dso_memory_pool); + j2cimpl_dso_memory_pool()); //now, check for success if ( rv == APR_SUCCESS ) @@ -152,11 +151,7 @@ void LLImageJ2C::openDSO() j2cimpl_dso_handle = NULL; } - if ( j2cimpl_dso_memory_pool ) - { - apr_pool_destroy(j2cimpl_dso_memory_pool); - j2cimpl_dso_memory_pool = NULL; - } + j2cimpl_dso_memory_pool.destroy(); } } @@ -164,7 +159,7 @@ void LLImageJ2C::openDSO() void LLImageJ2C::closeDSO() { if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle); - if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool); + j2cimpl_dso_memory_pool.destroy(); } //static diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index aceebf781..79353d55b 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -41,20 +41,13 @@ LLImageDecodeThread::LLImageDecodeThread(bool threaded) : LLQueuedThread("imagedecode", threaded) { - mCreationMutex = new LLMutex(getAPRPool()); -} - -//virtual -LLImageDecodeThread::~LLImageDecodeThread() -{ - delete mCreationMutex ; } // MAIN THREAD // virtual S32 LLImageDecodeThread::update(U32 max_time_ms) { - LLMutexLock lock(mCreationMutex); + LLMutexLock lock(&mCreationMutex); for (creation_list_t::iterator iter = mCreationList.begin(); iter != mCreationList.end(); ++iter) { @@ -77,7 +70,7 @@ S32 LLImageDecodeThread::update(U32 max_time_ms) LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, U32 priority, S32 discard, BOOL needs_aux, Responder* responder) { - LLMutexLock lock(mCreationMutex); + LLMutexLock lock(&mCreationMutex); handle_t handle = generateHandle(); mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); return handle; @@ -87,7 +80,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* // Returns the size of the mutex guarded list as an indication of sanity S32 LLImageDecodeThread::tut_size() { - LLMutexLock lock(mCreationMutex); + LLMutexLock lock(&mCreationMutex); S32 res = mCreationList.size(); return res; } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 9a09f81bc..2703af497 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -78,8 +78,6 @@ public: public: LLImageDecodeThread(bool threaded = true); - virtual ~LLImageDecodeThread(); - handle_t decodeImage(LLImageFormatted* image, U32 priority, S32 discard, BOOL needs_aux, Responder* responder); @@ -103,7 +101,7 @@ private: }; typedef std::list creation_list_t; creation_list_t mCreationList; - LLMutex* mCreationMutex; + LLMutex mCreationMutex; }; #endif diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 53641fcea..8bfebcb42 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -55,7 +55,7 @@ LLVolumeMgr::LLVolumeMgr() { // the LLMutex magic interferes with easy unit testing, // so you now must manually call useMutex() to use it - //mDataMutex = new LLMutex(gAPRPoolp); + //mDataMutex = new LLMutex; } LLVolumeMgr::~LLVolumeMgr() @@ -222,7 +222,7 @@ void LLVolumeMgr::useMutex() { if (!mDataMutex) { - mDataMutex = new LLMutex(gAPRPoolp); + mDataMutex = new LLMutex; } } diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 7a2dc6cc3..93079f537 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -44,6 +44,7 @@ #include "llapr.h" #define CARES_STATICLIB #include "llares.h" +#include "llscopedvolatileaprpool.h" #if defined(LL_WINDOWS) # define ns_c_in 1 @@ -467,11 +468,6 @@ void LLAres::search(const std::string &query, LLResType type, bool LLAres::process(U64 timeout) { - if (!gAPRPoolp) - { - ll_init_apr(); - } - ares_socket_t socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_int32_t nsds = 0; @@ -485,10 +481,7 @@ bool LLAres::process(U64 timeout) return nsds > 0; } - apr_status_t status; - LLAPRPool pool; - status = pool.getStatus() ; - ll_apr_assert_status(status); + LLScopedVolatileAPRPool scoped_pool; for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) { @@ -505,7 +498,7 @@ bool LLAres::process(U64 timeout) apr_socket_t *aprSock = NULL; - status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); + apr_status_t status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], scoped_pool); if (status != APR_SUCCESS) { ll_apr_warn_status(status); @@ -514,7 +507,7 @@ bool LLAres::process(U64 timeout) aprFds[nactive].desc.s = aprSock; aprFds[nactive].desc_type = APR_POLL_SOCKET; - aprFds[nactive].p = pool.getAPRPool(); + aprFds[nactive].p = scoped_pool; aprFds[nactive].rtnevents = 0; aprFds[nactive].client_data = &socks[i]; @@ -523,7 +516,7 @@ bool LLAres::process(U64 timeout) if (nactive > 0) { - status = apr_poll(aprFds, nactive, &nsds, timeout); + apr_status_t status = apr_poll(aprFds, nactive, &nsds, timeout); if (status != APR_SUCCESS && status != APR_TIMEUP) { diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index f43bafd45..38b2bea1b 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1082,7 +1082,7 @@ void LLCurl::initClass() S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; i factory_ptr(factory); - LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr); + LLIOServerSocket* server = new LLIOServerSocket(socket, factory_ptr); LLPumpIO::chain_t chain; chain.push_back(LLIOPipe::ptr_t(server)); diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index e8e390f29..66e763444 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -56,7 +56,7 @@ class LLIOHTTPServer public: typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data); - static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port); + static LLHTTPNode& create(LLPumpIO& pump, U16 port); /**< Creates an HTTP wire server on the pump for the given TCP port. * * Returns the root node of the new server. Add LLHTTPNode instances diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 7ec577c7b..686c03742 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -41,6 +41,7 @@ #include "llhost.h" #include "llmemtype.h" #include "llpumpio.h" +#include "llthread.h" // // constants @@ -104,51 +105,31 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock) /// // static -LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) +LLSocket::ptr_t LLSocket::create(EType type, U16 port) { LLMemType m1(LLMemType::MTYPE_IO_TCP); - LLSocket::ptr_t rv; - apr_socket_t* socket = NULL; - apr_pool_t* new_pool = NULL; apr_status_t status = APR_EGENERAL; - - // create a pool for the socket - status = apr_pool_create(&new_pool, pool); - if(ll_apr_warn_status(status)) - { - if(new_pool) apr_pool_destroy(new_pool); - return rv; - } + LLSocket::ptr_t rv(new LLSocket); if(STREAM_TCP == type) { - status = apr_socket_create( - &socket, - APR_INET, - SOCK_STREAM, - APR_PROTO_TCP, - new_pool); + status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, rv->mPool()); } else if(DATAGRAM_UDP == type) { - status = apr_socket_create( - &socket, - APR_INET, - SOCK_DGRAM, - APR_PROTO_UDP, - new_pool); + status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, rv->mPool()); } else { - if(new_pool) apr_pool_destroy(new_pool); + rv.reset(); return rv; } if(ll_apr_warn_status(status)) { - if(new_pool) apr_pool_destroy(new_pool); + rv->mSocket = NULL; + rv.reset(); return rv; } - rv = ptr_t(new LLSocket(socket, new_pool)); if(port > 0) { apr_sockaddr_t* sa = NULL; @@ -158,7 +139,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) APR_UNSPEC, port, 0, - new_pool); + rv->mPool()); if(ll_apr_warn_status(status)) { rv.reset(); @@ -166,8 +147,8 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) } // This allows us to reuse the address on quick down/up. This // is unlikely to create problems. - ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1)); - status = apr_socket_bind(socket, sa); + ll_apr_warn_status(apr_socket_opt_set(rv->mSocket, APR_SO_REUSEADDR, 1)); + status = apr_socket_bind(rv->mSocket, sa); if(ll_apr_warn_status(status)) { rv.reset(); @@ -181,7 +162,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) // to keep a queue of incoming connections for ACCEPT. lldebugs << "Setting listen state for socket." << llendl; status = apr_socket_listen( - socket, + rv->mSocket, LL_DEFAULT_LISTEN_BACKLOG); if(ll_apr_warn_status(status)) { @@ -202,21 +183,28 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) } // static -LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool) +LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket) { LLMemType m1(LLMemType::MTYPE_IO_TCP); - LLSocket::ptr_t rv; - if(!socket) + if (!listen_socket->getSocket()) { + status = APR_ENOSOCKET; + return LLSocket::ptr_t(); + } + LLSocket::ptr_t rv(new LLSocket); + lldebugs << "accepting socket" << llendl; + status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool()); + if (status != APR_SUCCESS) + { + rv->mSocket = NULL; + rv.reset(); return rv; } - rv = ptr_t(new LLSocket(socket, pool)); rv->mPort = PORT_EPHEMERAL; rv->setOptions(); return rv; } - bool LLSocket::blockingConnect(const LLHost& host) { if(!mSocket) return false; @@ -229,7 +217,7 @@ bool LLSocket::blockingConnect(const LLHost& host) APR_UNSPEC, host.getPort(), 0, - mPool))) + mPool()))) { return false; } @@ -240,13 +228,11 @@ bool LLSocket::blockingConnect(const LLHost& host) return true; } -LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) : - mSocket(socket), - mPool(pool), +LLSocket::LLSocket() : + mSocket(NULL), + mPool(LLThread::tldata().mRootPool), mPort(PORT_INVALID) { - ll_debug_socket("Constructing wholely formed socket", mSocket); - LLMemType m1(LLMemType::MTYPE_IO_TCP); } LLSocket::~LLSocket() @@ -258,10 +244,6 @@ LLSocket::~LLSocket() ll_debug_socket("Destroying socket", mSocket); apr_socket_close(mSocket); } - if(mPool) - { - apr_pool_destroy(mPool); - } } void LLSocket::setOptions() @@ -522,10 +504,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( /// LLIOServerSocket::LLIOServerSocket( - apr_pool_t* pool, LLIOServerSocket::socket_t listener, factory_t factory) : - mPool(pool), mListenSocket(listener), mReactor(factory), mInitialized(false), @@ -585,21 +565,15 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( lldebugs << "accepting socket" << llendl; PUMP_DEBUG; - apr_pool_t* new_pool = NULL; - apr_status_t status = apr_pool_create(&new_pool, mPool); - apr_socket_t* socket = NULL; - status = apr_socket_accept( - &socket, - mListenSocket->getSocket(), - new_pool); - LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool)); + apr_status_t status; + LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket)); //EStatus rv = STATUS_ERROR; - if(llsocket) + if(llsocket && status == APR_SUCCESS) { PUMP_DEBUG; apr_sockaddr_t* remote_addr; - apr_socket_addr_get(&remote_addr, APR_REMOTE, socket); + apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket()); char* remote_host_string; apr_sockaddr_ip_get(&remote_host_string, remote_addr); @@ -614,7 +588,6 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( { chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket))); pump->addChain(chain, mResponseTimeout); - status = STATUS_OK; } else { @@ -623,7 +596,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( } else { - llwarns << "Unable to create linden socket." << llendl; + char buf[256]; + llwarns << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << llendl; } PUMP_DEBUG; @@ -636,11 +610,10 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( #if 0 LLIODataSocket::LLIODataSocket( U16 suggested_port, - U16 start_discovery_port, - apr_pool_t* pool) : + U16 start_discovery_port) : mSocket(NULL) { - if(!pool || (PORT_INVALID == suggested_port)) return; + if(PORT_INVALID == suggested_port) return; if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return; apr_sockaddr_t* sa = NULL; if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return; diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index ec09ad8ba..5ad75e909 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -44,7 +44,6 @@ */ #include "lliopipe.h" -#include "apr_pools.h" #include "apr_network_io.h" #include "llchainio.h" @@ -94,34 +93,22 @@ public: * socket. If you intend the socket to be known to external * clients without prior port notification, do not use * PORT_EPHEMERAL. - * @param pool The apr pool to use. A child pool will be created - * and associated with the socket. * @param type The type of socket to create * @param port The port for the socket * @return A valid socket shared pointer if the call worked. */ static ptr_t create( - apr_pool_t* pool, EType type, U16 port = PORT_EPHEMERAL); /** - * @brief Create a LLSocket when you already have an apr socket. + * @brief Create a LLSocket by accepting a connection from a listen socket. * - * This method assumes an ephemeral port. This is typically used - * by calls which spawn a socket such as a call to - * accept() as in the server socket. This call should - * not fail if you have a valid apr socket. - * Because of the nature of how accept() works, you are expected - * to create a new pool for the socket, use that pool for the - * accept, and pass it in here where it will be bound with the - * socket and destroyed at the same time. - * @param socket The apr socket to use - * @param pool The pool used to create the socket. *NOTE: The pool - * passed in will be DESTROYED. + * @param status Output. Status of the accept if a valid listen socket was passed. + * @param listen_socket The listen socket to use. * @return A valid socket shared pointer if the call worked. */ - static ptr_t create(apr_socket_t* socket, apr_pool_t* pool); + static ptr_t create(apr_status_t& status, ptr_t& listen_socket); /** * @brief Perform a blocking connect to a host. Do not use in production. @@ -156,7 +143,7 @@ protected: * @brief Protected constructor since should only make sockets * with one of the two create() calls. */ - LLSocket(apr_socket_t* socket, apr_pool_t* pool); + LLSocket(void); /** * @brief Set default socket options. @@ -173,8 +160,8 @@ protected: // The apr socket. apr_socket_t* mSocket; - // our memory pool - apr_pool_t* mPool; + // Our memory pool. + AIAPRPool mPool; // The port if we know it. U16 mPort; @@ -299,7 +286,7 @@ class LLIOServerSocket : public LLIOPipe public: typedef LLSocket::ptr_t socket_t; typedef boost::shared_ptr factory_t; - LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor); + LLIOServerSocket(socket_t listener, factory_t reactor); virtual ~LLIOServerSocket(); /** @@ -331,7 +318,6 @@ protected: //@} protected: - apr_pool_t* mPool; socket_t mListenSocket; factory_t mReactor; bool mInitialized; @@ -365,8 +351,7 @@ public: */ LLIODataSocket( U16 suggested_port, - U16 start_discovery_port, - apr_pool_t* pool); + U16 start_discovery_port); virtual ~LLIODataSocket(); protected: diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index ce206d8d7..e55a1bb41 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -56,6 +56,7 @@ #include "llstring.h" #include "lluuid.h" #include "net.h" +#include "aiaprpool.h" // // constants @@ -63,7 +64,7 @@ const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096; static bool gMailEnabled = true; -static apr_pool_t* gMailPool; +static AIAPRPool gMailPool; static apr_sockaddr_t* gSockAddr; static apr_socket_t* gMailSocket; @@ -88,7 +89,7 @@ bool connect_smtp() gSockAddr->sa.sin.sin_family, SOCK_STREAM, APR_PROTO_TCP, - gMailPool); + gMailPool()); if(ll_apr_warn_status(status)) return false; status = apr_socket_connect(gMailSocket, gSockAddr); if(ll_apr_warn_status(status)) @@ -145,19 +146,19 @@ BOOL LLMail::send( } // static -void LLMail::init(const std::string& hostname, apr_pool_t* pool) +void LLMail::init(const std::string& hostname) { gMailSocket = NULL; - if(hostname.empty() || !pool) + if (hostname.empty()) { - gMailPool = NULL; gSockAddr = NULL; + gMailPool.destroy(); } else { - gMailPool = pool; + gMailPool.create(); - // collect all the information into a socaddr sturcture. the + // Collect all the information into a sockaddr structure. the // documentation is a bit unclear, but I either have to // specify APR_UNSPEC or not specify any flags. I am not sure // which option is better. @@ -167,7 +168,7 @@ void LLMail::init(const std::string& hostname, apr_pool_t* pool) APR_UNSPEC, 25, APR_IPV4_ADDR_OK, - gMailPool); + gMailPool()); ll_apr_warn_status(status); } } diff --git a/indra/llmessage/llmail.h b/indra/llmessage/llmail.h index 7effb847a..7026d93b3 100644 --- a/indra/llmessage/llmail.h +++ b/indra/llmessage/llmail.h @@ -33,15 +33,13 @@ #ifndef LL_LLMAIL_H #define LL_LLMAIL_H -typedef struct apr_pool_t apr_pool_t; - #include "llsd.h" class LLMail { public: // if hostname is NULL, then the host is resolved as 'mail' - static void init(const std::string& hostname, apr_pool_t* pool); + static void init(const std::string& hostname); // Allow all email transmission to be disabled/enabled. static void enable(bool mail_enabled); diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 2f86269ea..c50dcc876 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -43,6 +43,7 @@ #include "llmemtype.h" #include "llstl.h" #include "llstat.h" +#include "llthread.h" #include "llfasttimer.h" #include //VS2010 @@ -170,14 +171,12 @@ struct ll_delete_apr_pollset_fd_client_data /** * LLPumpIO */ -LLPumpIO::LLPumpIO(apr_pool_t* pool) : +LLPumpIO::LLPumpIO(void) : mState(LLPumpIO::NORMAL), mRebuildPollset(false), mPollset(NULL), mPollsetClientID(0), mNextLock(0), - mPool(NULL), - mCurrentPool(NULL), mCurrentPoolReallocCount(0), mChainsMutex(NULL), mCallbackMutex(NULL), @@ -186,21 +185,24 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) : mCurrentChain = mRunningChains.end(); LLMemType m1(LLMemType::MTYPE_IO_PUMP); - initialize(pool); + initialize(); } LLPumpIO::~LLPumpIO() { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - cleanup(); -} - -bool LLPumpIO::prime(apr_pool_t* pool) -{ - LLMemType m1(LLMemType::MTYPE_IO_PUMP); - cleanup(); - initialize(pool); - return ((pool == NULL) ? false : true); +#if LL_THREADS_APR + if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex); + if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex); +#endif + mChainsMutex = NULL; + mCallbackMutex = NULL; + if(mPollset) + { +// lldebugs << "cleaning up pollset" << llendl; + apr_pollset_destroy(mPollset); + mPollset = NULL; + } } bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) @@ -360,8 +362,7 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll) { // each fd needs a pool to work with, so if one was // not specified, use this pool. - // *FIX: Should it always be this pool? - value.second.p = mPool; + value.second.p = (*mCurrentChain).mDescriptorsPool->operator()(); } value.second.client_data = new S32(++mPollsetClientID); (*mCurrentChain).mDescriptors.push_back(value); @@ -828,39 +829,15 @@ void LLPumpIO::control(LLPumpIO::EControl op) } } -void LLPumpIO::initialize(apr_pool_t* pool) +void LLPumpIO::initialize(void) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - if(!pool) return; + mPool.create(); #if LL_THREADS_APR // SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly. - apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool); - apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool); + apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); + apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); #endif - mPool = pool; -} - -void LLPumpIO::cleanup() -{ - LLMemType m1(LLMemType::MTYPE_IO_PUMP); -#if LL_THREADS_APR - if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex); - if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex); -#endif - mChainsMutex = NULL; - mCallbackMutex = NULL; - if(mPollset) - { -// lldebugs << "cleaning up pollset" << llendl; - apr_pollset_destroy(mPollset); - mPollset = NULL; - } - if(mCurrentPool) - { - apr_pool_destroy(mCurrentPool); - mCurrentPool = NULL; - } - mPool = NULL; } void LLPumpIO::rebuildPollset() @@ -888,21 +865,19 @@ void LLPumpIO::rebuildPollset() if(mCurrentPool && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT))) { - apr_pool_destroy(mCurrentPool); - mCurrentPool = NULL; + mCurrentPool.destroy(); mCurrentPoolReallocCount = 0; } if(!mCurrentPool) { - apr_status_t status = apr_pool_create(&mCurrentPool, mPool); - (void)ll_apr_warn_status(status); + mCurrentPool.create(mPool); } // add all of the file descriptors run_it = mRunningChains.begin(); LLChainInfo::conditionals_t::iterator fd_it; LLChainInfo::conditionals_t::iterator fd_end; - apr_pollset_create(&mPollset, size, mCurrentPool, 0); + apr_pollset_create(&mPollset, size, mCurrentPool(), 0); for(; run_it != run_end; ++run_it) { fd_it = (*run_it).mDescriptors.begin(); @@ -1160,7 +1135,8 @@ bool LLPumpIO::handleChainError( LLPumpIO::LLChainInfo::LLChainInfo() : mInit(false), mLock(0), - mEOS(false) + mEOS(false), + mDescriptorsPool(new AIAPRPool(LLThread::tldata().mRootPool)) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index fc0bfabaa..2666be04a 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -36,11 +36,12 @@ #define LL_LLPUMPIO_H #include +#include #if LL_LINUX // needed for PATH_MAX in APR. #include #endif -#include "apr_pools.h" +#include "aiaprpool.h" #include "llbuffer.h" #include "llframetimer.h" #include "lliopipe.h" @@ -64,9 +65,8 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS; * pump() on a thread used for IO and call * respond() on a thread that is expected to do higher * level processing. You can call almost any other method from any - * thread - see notes for each method for details. In order for the - * threading abstraction to work, you need to call prime() - * with a valid apr pool. + * thread - see notes for each method for details. + * * A pump instance manages much of the state for the pipe, including * the list of pipes in the chain, the channel for each element in the * chain, the buffer, and if any pipe has marked the stream or process @@ -85,24 +85,13 @@ public: /** * @brief Constructor. */ - LLPumpIO(apr_pool_t* pool); + LLPumpIO(void); /** * @brief Destructor. */ ~LLPumpIO(); - /** - * @brief Prepare this pump for usage. - * - * If you fail to call this method prior to use, the pump will - * try to work, but will not come with any thread locking - * mechanisms. - * @param pool The apr pool to use. - * @return Returns true if the pump is primed. - */ - bool prime(apr_pool_t* pool); - /** * @brief Typedef for having a chain of pipes. */ @@ -374,6 +363,7 @@ protected: typedef std::pair pipe_conditional_t; typedef std::vector conditionals_t; conditionals_t mDescriptors; + boost::shared_ptr mDescriptorsPool; }; // All the running chains & info @@ -392,9 +382,9 @@ protected: callbacks_t mPendingCallbacks; callbacks_t mCallbacks; - // memory allocator for pollsets & mutexes. - apr_pool_t* mPool; - apr_pool_t* mCurrentPool; + // Memory pool for pollsets & mutexes. + AIAPRPool mPool; + AIAPRPool mCurrentPool; S32 mCurrentPoolReallocCount; #if LL_THREADS_APR @@ -406,8 +396,7 @@ protected: #endif protected: - void initialize(apr_pool_t* pool); - void cleanup(); + void initialize(); /** * @brief Given the internal state of the chains, rebuild the pollset diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp old mode 100755 new mode 100644 diff --git a/indra/llmessage/llsdmessagebuilder.h b/indra/llmessage/llsdmessagebuilder.h old mode 100755 new mode 100644 diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp old mode 100755 new mode 100644 diff --git a/indra/llmessage/llsdmessagereader.h b/indra/llmessage/llsdmessagereader.h old mode 100755 new mode 100644 diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 46e976fe3..87f011643 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -45,6 +45,7 @@ #include "llstring.h" #include "apr_env.h" #include "llapr.h" +#include "llscopedvolatileaprpool.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -161,27 +162,31 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback) // is called with use_proxy = FALSE void LLURLRequest::useProxy(bool use_proxy) { - static char *env_proxy; + static std::string env_proxy; - if (use_proxy && (env_proxy == NULL)) + if (use_proxy && env_proxy.empty()) { - apr_status_t status; - LLAPRPool pool; - status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool()); + char* env_proxy_str; + LLScopedVolatileAPRPool scoped_pool; + apr_status_t status = apr_env_get(&env_proxy_str, "ALL_PROXY", scoped_pool); if (status != APR_SUCCESS) { - status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool()); + status = apr_env_get(&env_proxy_str, "http_proxy", scoped_pool); } if (status != APR_SUCCESS) { - use_proxy = FALSE; + use_proxy = false; } + else + { + // env_proxy_str is stored in the scoped_pool, so we have to make a copy. + env_proxy = env_proxy_str; + } } + lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl; - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; - - if (env_proxy && use_proxy) + if (use_proxy) { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); } diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 677052d65..d0572fb4a 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -107,8 +107,10 @@ std::string get_shared_secret(); class LLMessagePollInfo { public: + LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { } apr_socket_t *mAPRSocketp; apr_pollfd_t mPollFD; + AIAPRPool mPool; }; namespace @@ -297,20 +299,13 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, } // LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl; - // - // Create the data structure that we can poll on - // - if (!gAPRPoolp) - { - LL_ERRS("Messaging") << "No APR pool before message system initialization!" << llendl; - ll_init_apr(); - } - apr_socket_t *aprSocketp = NULL; - apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp); - mPollInfop = new LLMessagePollInfo; + + apr_socket_t *aprSocketp = NULL; + apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool()); + mPollInfop->mAPRSocketp = aprSocketp; - mPollInfop->mPollFD.p = gAPRPoolp; + mPollInfop->mPollFD.p = mPollInfop->mPool(); mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET; mPollInfop->mPollFD.reqevents = APR_POLLIN; mPollInfop->mPollFD.rtnevents = 0; diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp old mode 100755 new mode 100644 index b822b9e94..3a1395cd2 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -36,8 +36,7 @@ #include "linden_common.h" #include "llplugininstance.h" - -#include "llapr.h" +#include "aiaprpool.h" /** Virtual destructor. */ LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener() @@ -86,7 +85,7 @@ int LLPluginInstance::load(std::string &plugin_file) int result = apr_dso_load(&mDSOHandle, plugin_file.c_str(), - gAPRPoolp); + AIAPRRootPool::get()()); if(result != APR_SUCCESS) { char buf[1024]; diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginmessage.cpp b/indra/llplugin/llpluginmessage.cpp old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginmessage.h b/indra/llplugin/llpluginmessage.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginmessageclasses.h b/indra/llplugin/llpluginmessageclasses.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp old mode 100755 new mode 100644 index 8168b32c4..ebac3c52b --- a/indra/llplugin/llpluginmessagepipe.cpp +++ b/indra/llplugin/llpluginmessagepipe.cpp @@ -99,8 +99,6 @@ void LLPluginMessagePipeOwner::killMessagePipe(void) } LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket): - mInputMutex(gAPRPoolp), - mOutputMutex(gAPRPoolp), mOwner(owner), mSocket(socket) { diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp old mode 100755 new mode 100644 index 8dbf2b3e9..d2238236f --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -47,7 +47,7 @@ LLPluginProcessChild::LLPluginProcessChild() { mState = STATE_UNINITIALIZED; mInstance = NULL; - mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + mSocket = LLSocket::create(LLSocket::STREAM_TCP); mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz mCPUElapsed = 0.0f; mBlockingRequest = false; diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h old mode 100755 new mode 100644 diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp old mode 100755 new mode 100644 index 8fd18ef05..2cb6b2832 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -49,6 +49,7 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner() bool LLPluginProcessParent::sUseReadThread = false; apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; +AIAPRPool LLPluginProcessParent::sPollSetPool; bool LLPluginProcessParent::sPollsetNeedsRebuild = false; LLMutex *LLPluginProcessParent::sInstancesMutex; std::list LLPluginProcessParent::sInstances; @@ -59,7 +60,7 @@ class LLPluginProcessParentPollThread: public LLThread { public: LLPluginProcessParentPollThread() : - LLThread("LLPluginProcessParentPollThread", gAPRPoolp) + LLThread("LLPluginProcessParentPollThread") { } protected: @@ -84,12 +85,11 @@ protected: }; -LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): - mIncomingQueueMutex(gAPRPoolp) +LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) { if(!sInstancesMutex) { - sInstancesMutex = new LLMutex(gAPRPoolp); + sInstancesMutex = new LLMutex; } mOwner = owner; @@ -102,6 +102,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): mBlocked = false; mPolledInput = false; mPollFD.client_data = NULL; + mPollFDPool.create(); mPluginLaunchTimeout = 60.0f; mPluginLockupTimeout = 15.0f; @@ -177,44 +178,28 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std bool LLPluginProcessParent::accept() { bool result = false; - apr_status_t status = APR_EGENERAL; - apr_socket_t *new_socket = NULL; - - status = apr_socket_accept( - &new_socket, - mListenSocket->getSocket(), - gAPRPoolp); + mSocket = LLSocket::create(status, mListenSocket); if(status == APR_SUCCESS) { // llinfos << "SUCCESS" << llendl; // Success. Create a message pipe on the new socket - - // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor! - apr_pool_t* new_pool = NULL; - status = apr_pool_create(&new_pool, gAPRPoolp); - - mSocket = LLSocket::create(new_socket, new_pool); new LLPluginMessagePipe(this, mSocket); result = true; } - else if(APR_STATUS_IS_EAGAIN(status)) - { -// llinfos << "EAGAIN" << llendl; - - // No incoming connections. This is not an error. - status = APR_SUCCESS; - } else { -// llinfos << "Error:" << llendl; - ll_apr_warn_status(status); - - // Some other error. - errorState(); + mSocket.reset(); + // EAGAIN means "No incoming connections". This is not an error. + if (!APR_STATUS_IS_EAGAIN(status)) + { + // Some other error. + ll_apr_warn_status(status); + errorState(); + } } return result; @@ -283,7 +268,7 @@ void LLPluginProcessParent::idle(void) apr_status_t status = APR_SUCCESS; apr_sockaddr_t* addr = NULL; - mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + mListenSocket = LLSocket::create(LLSocket::STREAM_TCP); mBoundPort = 0; // This code is based on parts of LLSocket::create() in lliosocket.cpp. @@ -294,7 +279,7 @@ void LLPluginProcessParent::idle(void) APR_INET, 0, // port 0 = ephemeral ("find me a port") 0, - gAPRPoolp); + AIAPRRootPool::get()()); if(ll_apr_warn_status(status)) { @@ -617,7 +602,8 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) if(message_pipe != NULL) { // Set up the apr_pollfd_t - mPollFD.p = gAPRPoolp; + + mPollFD.p = mPollFDPool(); mPollFD.desc_type = APR_POLL_SOCKET; mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; mPollFD.rtnevents = 0; @@ -664,6 +650,7 @@ void LLPluginProcessParent::updatePollset() // delete the existing pollset. apr_pollset_destroy(sPollSet); sPollSet = NULL; + sPollSetPool.destroy(); } std::list::iterator iter; @@ -686,12 +673,14 @@ void LLPluginProcessParent::updatePollset() { #ifdef APR_POLLSET_NOCOPY // The pollset doesn't exist yet. Create it now. - apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); + sPollSetPool.create(); + apr_status_t status = apr_pollset_create(&sPollSet, count, sPollSetPool(), APR_POLLSET_NOCOPY); if(status != APR_SUCCESS) { #endif // APR_POLLSET_NOCOPY LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; sPollSet = NULL; + sPollSetPool.destroy(); #ifdef APR_POLLSET_NOCOPY } else diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h old mode 100755 new mode 100644 index 95f5f70c5..bba3643d6 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -186,7 +186,9 @@ private: static bool sUseReadThread; apr_pollfd_t mPollFD; + AIAPRPool mPollFDPool; static apr_pollset_t *sPollSet; + static AIAPRPool sPollSetPool; static bool sPollsetNeedsRebuild; static LLMutex *sInstancesMutex; static std::list sInstances; diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp old mode 100755 new mode 100644 index e8a411a53..883d7b634 --- a/indra/llplugin/llpluginsharedmemory.cpp +++ b/indra/llplugin/llpluginsharedmemory.cpp @@ -201,7 +201,8 @@ bool LLPluginSharedMemory::create(size_t size) mName += createName(); mSize = size; - apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp ); + mPool.create(); + apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), mPool()); if(ll_apr_warn_status(status)) { @@ -224,7 +225,7 @@ bool LLPluginSharedMemory::destroy(void) } mImpl->mAprSharedMemory = NULL; } - + mPool.destroy(); return true; } @@ -233,7 +234,8 @@ bool LLPluginSharedMemory::attach(const std::string &name, size_t size) mName = name; mSize = size; - apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp ); + mPool.create(); + apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), mPool() ); if(ll_apr_warn_status(status)) { @@ -255,6 +257,7 @@ bool LLPluginSharedMemory::detach(void) } mImpl->mAprSharedMemory = NULL; } + mPool.destroy(); return true; } diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h old mode 100755 new mode 100644 index 081d311b3..669a3e409 --- a/indra/llplugin/llpluginsharedmemory.h +++ b/indra/llplugin/llpluginsharedmemory.h @@ -35,6 +35,8 @@ #ifndef LL_LLPLUGINSHAREDMEMORY_H #define LL_LLPLUGINSHAREDMEMORY_H +#include "aiaprpool.h" + class LLPluginSharedMemoryPlatformImpl; /** @@ -115,6 +117,7 @@ private: bool close(void); bool unlink(void); + AIAPRPool mPool; std::string mName; size_t mSize; void *mMappedAddress; diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp old mode 100755 new mode 100644 index 64c087bec..cca8ead8f --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -183,8 +183,6 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL int main(int argc, char **argv) #endif { - ll_init_apr(); - // Set up llerror logging { LLError::initForApplication("."); @@ -400,8 +398,6 @@ int main(int argc, char **argv) delete plugin; - ll_cleanup_apr(); - return 0; } diff --git a/indra/llui/llmemberlistener.h b/indra/llui/llmemberlistener.h old mode 100755 new mode 100644 diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 7748df84f..6bd4e4f22 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1194,13 +1194,13 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements) if (found != replacements.end()) { replacement = found->second; - //llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl; + //llinfos << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << llendl; it->second->setValue(replacement); } else { - llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl; + llwarns << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << llendl; } } } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3e4860763..3326524cb 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -58,6 +58,7 @@ #include "llimagegl.h" #include "llwindow.h" #include "lltextparser.h" +#include "lldir.h" #include #include "llmenugl.h" #include "../newview/lgghunspell_wrapper.h" @@ -4004,7 +4005,10 @@ void LLTextEditor::appendColoredText(const std::string &new_text, const std::string& font_name) { LLColor4 lcolor=color; - if (mParseHighlights) + // If LindenUserDir is empty then we didn't login yet. + // In that case we can't instantiate LLTextParser, which + // is initialized per user. + if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty()) { LLTextParser* highlight = LLTextParser::getInstance(); highlight->parseFullLineHighlights(new_text, &lcolor); @@ -4082,7 +4086,10 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text, S32 highlight_part, LLStyleSP stylep) { - if (mParseHighlights) + // If LindenUserDir is empty then we didn't login yet. + // In that case we can't instantiate LLTextParser, which + // is initialized per user. + if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty()) { LLTextParser* highlight = LLTextParser::getInstance(); diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp old mode 100755 new mode 100644 diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h old mode 100755 new mode 100644 diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index d495176de..29b50d7bc 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -193,8 +193,9 @@ const std::string &LLDir::getOSUserAppDir() const return mOSUserAppDir; } -const std::string &LLDir::getLindenUserDir() const +const std::string &LLDir::getLindenUserDir(bool empty_ok) const { + llassert(empty_ok || !mLindenUserDir.empty()); return mLindenUserDir; } diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 4111f4ffa..a90b8ab24 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -92,7 +92,7 @@ class LLDir const std::string &getAppRODataDir() const; // Location of read-only data files const std::string &getOSUserDir() const; // Location of the os-specific user dir const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir - const std::string &getLindenUserDir() const; // Location of the Linden user dir. + const std::string &getLindenUserDir(bool empty_ok = false) const; // Location of the Linden user dir. const std::string &getChatLogsDir() const; // Location of the chat logs dir. const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir. const std::string &getTempDir() const; // Common temporary directory diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 6a5834fec..ce6b1885f 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -97,7 +97,7 @@ LLDir_Linux::LLDir_Linux() mAppRODataDir = tmp_str; mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; - mLindenUserDir = tmp_str; + mLindenUserDir = ""; char path [32]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index a39e13fcf..2ebd6e471 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -100,7 +100,7 @@ LLDir_Solaris::LLDir_Solaris() mAppRODataDir = strdup(tmp_str); mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; - mLindenUserDir = tmp_str; + mLindenUserDir = ""; char path [LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp old mode 100755 new mode 100644 diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h old mode 100755 new mode 100644 diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 18c3951fd..1f4c991b2 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -219,7 +219,7 @@ const S32 LLVFSFileBlock::SERIAL_SIZE = 34; LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash) : mRemoveAfterCrash(remove_after_crash) { - mDataMutex = new LLMutex(0); + mDataMutex = new LLMutex; S32 i; for (i = 0; i < VFSLOCK_COUNT; i++) @@ -566,8 +566,9 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename } } - LL_WARNS("VFS") << "Using index file " << mIndexFilename << LL_ENDL; - LL_WARNS("VFS") << "Using data file " << mDataFilename << LL_ENDL; + // Success! + LL_INFOS("VFS") << "Using index file " << mIndexFilename << LL_ENDL; + LL_INFOS("VFS") << "Using data file " << mDataFilename << LL_ENDL; mValid = VFSVALID_OK; } diff --git a/indra/llwindow/glh/glh_linear.h b/indra/llwindow/glh/glh_linear.h old mode 100755 new mode 100644 diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index f57646b8e..3e6b1d0e4 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -66,7 +66,20 @@ const S32 CURRENT_VERSION = 101; //So, a global it is! bool gCOAEnabled = false; -LLControlVariable *LLControlVariable::getCOAActive() +LLControlVariable* LLControlVariable::getCOAActive() +{ + //if no coa connection, return 'this' + //if per account is ON and this IS a parent, return child var + //if per account is ON and this IS NOT a parent, return 'this' + //if per account is OFF and this IS NOT a parent, return parent var + //if per account is OFF and this IS a parent, return 'this' + if(getCOAConnection() && gCOAEnabled == isCOAParent()) + return getCOAConnection(); + else + return this; +} + +LLControlVariable const* LLControlVariable::getCOAActive() const { //if no coa connection, return 'this' //if per account is ON and this IS a parent, return child var @@ -282,11 +295,9 @@ LLSD LLControlVariable::getSaveValue() const #if PROF_CTRL_CALLS std::vector> gSettingsCallMap; -#endif //PROF_CTRL_CALLS -LLPointer LLControlGroup::getControl(const std::string& name) + +static update_gSettingsCallMap(ctrl_name_table_t::const_iterator const& iter) { - ctrl_name_table_t::iterator iter = mNameTable.find(name); -#if PROF_CTRL_CALLS if(iter != mNameTable.end()) { std::vector>::iterator iter2 = gSettingsCallMap.begin(); @@ -302,13 +313,32 @@ LLPointer LLControlGroup::getControl(const std::string& name) if(iter2 == gSettingsCallMap.end()) gSettingsCallMap.push_back(std::pair(name.c_str(),1)); } +} +#endif //PROF_CTRL_CALLS + +LLControlVariable* LLControlGroup::getControl(std::string const& name) +{ + ctrl_name_table_t::iterator iter = mNameTable.find(name); +#if PROF_CTRL_CALLS + update_gSettingsCallMap(iter); #endif //PROF_CTRL_CALLS if(iter != mNameTable.end()) return iter->second->getCOAActive(); else - return LLPointer(); + return NULL; } +LLControlVariable const* LLControlGroup::getControl(std::string const& name) const +{ + ctrl_name_table_t::const_iterator iter = mNameTable.find(name); +#if PROF_CTRL_CALLS + update_gSettingsCallMap(iter); +#endif //PROF_CTRL_CALLS + if(iter != mNameTable.end()) + return iter->second->getCOAActive(); + else + return NULL; +} //////////////////////////////////////////////////////////////////////////// @@ -502,9 +532,9 @@ std::string LLControlGroup::findString(const std::string& name) return LLStringUtil::null; } -std::string LLControlGroup::getString(const std::string& name) +std::string LLControlGroup::getString(const std::string& name) const { - LLControlVariable* control = getControl(name); + LLControlVariable const* control = getControl(name); if (control && control->isType(TYPE_STRING)) return control->get().asString(); @@ -649,9 +679,9 @@ LLSD LLControlGroup::getLLSD(const std::string& name) return LLSD(); } -BOOL LLControlGroup::controlExists(const std::string& name) +BOOL LLControlGroup::controlExists(const std::string& name) const { - ctrl_name_table_t::iterator iter = mNameTable.find(name); + ctrl_name_table_t::const_iterator iter = mNameTable.find(name); return iter != mNameTable.end(); } diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 38c0be773..e5cbf7354 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -122,7 +122,7 @@ public: const std::string& getComment() const { return mComment; } eControlType type() { return mType; } - bool isType(eControlType tp) { return tp == mType; } + bool isType(eControlType tp) const { return tp == mType; } void resetToDefault(bool fire_signal = false); @@ -153,7 +153,8 @@ public: bool isCOA() const { return mIsCOA; } bool isCOAParent() const { return mIsCOAParent; } LLControlVariable *getCOAConnection() const { return mCOAConnectedVar; } - LLControlVariable *getCOAActive(); + LLControlVariable* getCOAActive(); + LLControlVariable const* getCOAActive() const; void setIsCOA(bool IsCOA) { mIsCOA=IsCOA; } void setCOAConnect(LLControlVariable *pConnect, bool IsParent) { @@ -185,7 +186,8 @@ public: ~LLControlGroup(); void cleanup(); - LLPointer getControl(const std::string& name); + LLControlVariable* getControl(std::string const& name); + LLControlVariable const* getControl(std::string const& name) const; struct ApplyFunctor { @@ -210,7 +212,7 @@ public: std::string findString(const std::string& name); - std::string getString(const std::string& name); + std::string getString(const std::string& name) const; LLWString getWString(const std::string& name); std::string getText(const std::string& name); LLVector3 getVector3(const std::string& name); @@ -245,7 +247,7 @@ public: void setValue(const std::string& name, const LLSD& val); - BOOL controlExists(const std::string& name); + BOOL controlExists(const std::string& name) const; // Returns number of controls loaded, 0 if failed // If require_declaration is false, will auto-declare controls it finds diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h index c4c04b98b..ef8ee18c9 100644 --- a/indra/llxml/llcontrolgroupreader.h +++ b/indra/llxml/llcontrolgroupreader.h @@ -46,7 +46,7 @@ public: LLControlGroupReader() {} virtual ~LLControlGroupReader() {} - virtual std::string getString(const std::string& name) = 0; + virtual std::string getString(const std::string& name) const = 0; //virtual LLWString getWString(const std::string& name) = 0; virtual std::string getText(const std::string& name) = 0; //virtual LLVector3 getVector3(const std::string& name) = 0; diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp old mode 100755 new mode 100644 diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h old mode 100755 new mode 100644 diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt index 56cefde4b..54dc5de1e 100644 --- a/indra/media_plugins/example/CMakeLists.txt +++ b/indra/media_plugins/example/CMakeLists.txt @@ -79,4 +79,4 @@ if (DARWIN) LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" ) -endif (DARWIN) \ No newline at end of file +endif (DARWIN) diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp old mode 100755 new mode 100644 diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt old mode 100755 new mode 100644 index 05f123660..3b1f67954 --- a/indra/media_plugins/webkit/CMakeLists.txt +++ b/indra/media_plugins/webkit/CMakeLists.txt @@ -27,6 +27,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} + ${LLQTWEBKIT_INCLUDE_DIR} ) diff --git a/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/indra/media_plugins/webkit/dummy_volume_catcher.cpp old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp old mode 100755 new mode 100644 index 085708640..321d1f91f --- a/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ b/indra/media_plugins/webkit/linux_volume_catcher.cpp @@ -50,7 +50,7 @@ extern "C" { #include #include // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. -#include "apr_pools.h" +#include "aiaprpool.h" #include "apr_dso.h" } @@ -66,7 +66,7 @@ extern "C" { #undef LL_PA_SYM static bool sSymsGrabbed = false; -static apr_pool_t *sSymPADSOMemoryPool = NULL; +static AIAPRPool sSymPADSOMemoryPool; static apr_dso_handle_t *sSymPADSOHandleG = NULL; bool grab_pa_syms(std::string pulse_dso_name) @@ -85,11 +85,11 @@ bool grab_pa_syms(std::string pulse_dso_name) #define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0) //attempt to load the shared library - apr_pool_create(&sSymPADSOMemoryPool, NULL); + sSymPADSOMemoryPool.create(); if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle, pulse_dso_name.c_str(), - sSymPADSOMemoryPool) )) + sSymPADSOMemoryPool()) )) { INFOMSG("Found DSO: %s", pulse_dso_name.c_str()); @@ -132,11 +132,7 @@ void ungrab_pa_syms() sSymPADSOHandleG = NULL; } - if ( sSymPADSOMemoryPool ) - { - apr_pool_destroy(sSymPADSOMemoryPool); - sSymPADSOMemoryPool = NULL; - } + sSymPADSOMemoryPool.destroy(); // NULL-out all of the symbols we'd grabbed #define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0) diff --git a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/volume_catcher.h b/indra/media_plugins/webkit/volume_catcher.h old mode 100755 new mode 100644 diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp old mode 100755 new mode 100644 diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index cecdbddbc..57a6163d7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1467,6 +1467,7 @@ if (LINUX) COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --standalone=${STANDALONE} --grid=${GRID} --channel=${VIEWER_CHANNEL} --login_channel=${VIEWER_LOGIN_CHANNEL} @@ -1591,17 +1592,17 @@ endif (LL_TESTS) # Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py if (WINDOWS) - #~ get_target_property(BUILT_LLCOMMON llcommon LOCATION) - #~ add_custom_command( - #~ TARGET ${VIEWER_BINARY_NAME} POST_BUILD - #~ COMMAND ${CMAKE_COMMAND} - #~ ARGS - #~ -E - #~ copy_if_different - #~ ${BUILT_LLCOMMON} - #~ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - #~ COMMENT "Copying llcommon.dll to the runtime folder." - #~ ) + get_target_property(BUILT_LLCOMMON llcommon LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_LLCOMMON} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMENT "Copying llcommon.dll to the runtime folder." + ) get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) add_custom_command( diff --git a/indra/newview/ascentdaycyclemanager.cpp b/indra/newview/ascentdaycyclemanager.cpp index b83168f64..43f243f08 100644 --- a/indra/newview/ascentdaycyclemanager.cpp +++ b/indra/newview/ascentdaycyclemanager.cpp @@ -134,10 +134,7 @@ void AscentDayCycleManager::loadPreset(const std::string & name,bool propagate) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(name); escaped_filename += ".xml"; @@ -186,10 +183,7 @@ void AscentDayCycleManager::loadPreset(const std::string & name,bool propagate) void AscentDayCycleManager::savePreset(const std::string & name) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(name); escaped_filename += ".xml"; @@ -340,10 +334,7 @@ bool AscentDayCycleManager::removeParamSet(const std::string& name, bool delete_ std::string path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/days", "")); // use full curl escaped name - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_name(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_name = LLWeb::curlEscape(name); gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml"); } diff --git a/indra/newview/hippofloaterxml.cpp b/indra/newview/hippofloaterxml.cpp old mode 100755 new mode 100644 diff --git a/indra/newview/hippofloaterxml.h b/indra/newview/hippofloaterxml.h old mode 100755 new mode 100644 diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index ba101cdf9..77dd4d023 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -7,7 +7,7 @@ ## - Avoids using any OpenAL audio driver. #export LL_BAD_OPENAL_DRIVER=x ## - Avoids using any FMOD audio driver. -export LL_BAD_FMOD_DRIVER=x +#export LL_BAD_FMOD_DRIVER=x ## - Avoids using the FMOD ESD audio driver. #export LL_BAD_FMOD_ESD=x @@ -45,6 +45,7 @@ export LL_BAD_FMOD_DRIVER=x ## disable these by enabling this option: #export LL_DISABLE_GSTREAMER=x + ## Everything below this line is just for advanced troubleshooters. ##------------------------------------------------------------------- @@ -53,15 +54,8 @@ export LL_BAD_FMOD_DRIVER=x ## you're building your own viewer, bear in mind that the executable ## in the bin directory will be stripped: you should replace it with ## an unstripped binary before you run. -## -## I keep crashing without having GDB running, always run it if an -## environment variable is set. - -if [ -n "$ASCENDED_DEVELOPER" ]; then -# export LL_WRAPPER='cgdb --args' - export LL_WRAPPER='gdb --args' -# export LL_WRAPPER='valgrind --smc-check=all --error-limit=no --log-file=secondlife.vg --leak-check=full --suppressions=/usr/lib/valgrind/glibc-2.5.supp --suppressions=secondlife-i686.supp' -fi +#export LL_WRAPPER='gdb --args' +#export LL_WRAPPER='valgrind --smc-check=all --error-limit=no --log-file=secondlife.vg --leak-check=full --suppressions=/usr/lib/valgrind/glibc-2.5.supp --suppressions=secondlife-i686.supp' ## - Avoids an often-buggy X feature that doesn't really benefit us anyway. export SDL_VIDEO_X11_DGAMOUSE=0 @@ -74,13 +68,6 @@ if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim fi -# Work around for a crash bug when restarting OpenGL after a change in the -# graphic settings (anti-aliasing, VBO, FSAA, full screen mode, UI scale). -# When you enable this work around, you can change the settings without -# crashing, but you will have to restart the viewer after changing them -# because the display still gets corrupted. -export LL_OPENGL_RESTART_CRASH_BUG=x - ## - Automatically work around the ATI mouse cursor crash bug: ## (this workaround is disabled as most fglrx users do not see the bug) #if lsmod | grep fglrx &>/dev/null ; then @@ -121,7 +108,13 @@ if [ -n "$LL_TCMALLOC" ]; then fi export VIEWER_BINARY='singularity-do-not-run-directly' -export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"' +BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)') +if [ "${BINARY_TYPE}" == "ELF 64-bit LSB executable" ]; then + export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib64:"`pwd`"/lib32:"${LD_LIBRARY_PATH}"' +else + export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}"' +fi + export SL_CMD='$LL_WRAPPER bin/$VIEWER_BINARY' export SL_OPT="`cat gridargs.dat` $@" @@ -134,27 +127,7 @@ if [ -n "$LL_RUN_ERR" ]; then if [ "$LL_RUN_ERR" = "runerr" ]; then # generic error running the binary echo '*** Bad shutdown. ***' - BINARY_TYPE=$(expr match "$(file -b ${RUN_PATH}/bin/SLPlugin)" '\(.*executable\)') - BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)') - if [ "${BINARY_SYSTEM}" == "ELF 64-bit LSB executable" -a "${BINARY_TYPE}" == "ELF 32-bit LSB executable" ]; then - echo - cat << EOFMARKER -You are running the Second Life Viewer on a x86_64 platform. The -most common problems when launching the Viewer (particularly -'bin/$VIEWER_BINARY: not found' and 'error while -loading shared libraries') may be solved by installing your Linux -distribution's 32-bit compatibility packages. -For example, on Ubuntu and other Debian-based Linuxes you might run: -$ sudo apt-get install ia32-libs ia32-libs-gtk ia32-libs-kde ia32-libs-sdl -EOFMARKER - fi + + fi fi - - -echo -echo '*******************************************************' -echo 'This is a BETA release of the Second Life linux client.' -echo 'Thank you for testing!' -echo 'Please see README-linux.txt before reporting problems.' -echo diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d9b80c9dc..420a9ae67 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -568,7 +568,10 @@ bool LLAppViewer::init() gDirUtilp->setSkinFolder("default"); initLogging(); - + + // Logging is initialized. Now it's safe to start the error thread. + startErrorThread(); + // gDeleteScheduler = new LLDeleteScheduler(); gBuildNewViewsScheduler = new LLBuildNewViewsScheduler(); @@ -857,7 +860,7 @@ bool LLAppViewer::mainLoop() //------------------------------------------- // Create IO Pump to use for HTTP Requests. - gServicePump = new LLPumpIO(gAPRPoolp); + gServicePump = new LLPumpIO; LLHTTPClient::setPump(*gServicePump); LLCurl::setCAFile(gDirUtilp->getCAFile()); @@ -1120,16 +1123,6 @@ bool LLAppViewer::mainLoop() bool LLAppViewer::cleanup() { - //---------------------------------------------- - //this test code will be removed after the test - //test manual call stack tracer - if(gSavedSettings.getBOOL("QAMode")) - { - LLError::LLCallStacks::print() ; - } - //end of the test code - //---------------------------------------------- - //flag all elements as needing to be destroyed immediately // to ensure shutdown order LLMortician::setZealous(TRUE); @@ -1588,8 +1581,9 @@ bool LLAppViewer::initLogging() return true; } -bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, - bool set_defaults) +bool LLAppViewer::loadSettingsFromDirectory(AIReadAccess const& settings_r, + std::string const& location_key, + bool set_defaults) { // Find and vet the location key. if(!mSettingsLocationList.has(location_key)) @@ -1616,11 +1610,13 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, LLSD files = location.get("Files"); for(LLSD::map_iterator itr = files.beginMap(); itr != files.endMap(); ++itr) { - std::string settings_group = (*itr).first; + std::string const settings_group = (*itr).first; + settings_map_type::const_iterator const settings_group_iter = settings_r->find(settings_group); + llinfos << "Attempting to load settings for the group " << settings_group << " - from location " << location_key << llendl; - if(gSettings.find(settings_group) == gSettings.end()) + if(settings_group_iter == settings_r->end()) { llwarns << "No matching settings group for name " << settings_group << llendl; continue; @@ -1634,11 +1630,10 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, std::string custom_name_setting = file.get("NameFromSetting"); // *NOTE: Regardless of the group currently being lodaed, // this setting is always read from the Global settings. - if(gSettings[sGlobalSettingsName]->controlExists(custom_name_setting)) + LLControlGroup const* control_group = settings_r->find(sGlobalSettingsName)->second; + if(control_group->controlExists(custom_name_setting)) { - std::string file_name = - gSettings[sGlobalSettingsName]->getString(custom_name_setting); - full_settings_path = file_name; + full_settings_path = control_group->getString(custom_name_setting); } } @@ -1654,7 +1649,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, requirement = file.get("Requirement").asInteger(); } - if(!gSettings[settings_group]->loadFromFile(full_settings_path, set_defaults)) + if(!settings_group_iter->second->loadFromFile(full_settings_path, set_defaults)) { if(requirement == 1) { @@ -1696,10 +1691,14 @@ std::string LLAppViewer::getSettingsFilename(const std::string& location_key, bool LLAppViewer::initConfiguration() { + // Grab and hold write locks for the entire duration of this function. + AIWriteAccess settings_w(gSettings); + settings_map_type& settings(*settings_w); + //Set up internal pointers - gSettings[sGlobalSettingsName] = &gSavedSettings; - gSettings[sPerAccountSettingsName] = &gSavedPerAccountSettings; - gSettings[sCrashSettingsName] = &gCrashSettings; + settings[sGlobalSettingsName] = &gSavedSettings; + settings[sPerAccountSettingsName] = &gSavedPerAccountSettings; + settings[sCrashSettingsName] = &gCrashSettings; //Load settings files list std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); @@ -1724,7 +1723,7 @@ bool LLAppViewer::initConfiguration() // - load defaults bool set_defaults = true; - if(!loadSettingsFromDirectory("Default", set_defaults)) + if(!loadSettingsFromDirectory(settings_w, "Default", set_defaults)) { std::ostringstream msg; msg << "Second Life could not load its default settings file. \n" @@ -1841,7 +1840,7 @@ bool LLAppViewer::initConfiguration() } // - load overrides from user_settings - loadSettingsFromDirectory("User"); + loadSettingsFromDirectory(settings_w, "User"); // - apply command line settings clp.notify(); @@ -1921,7 +1920,7 @@ bool LLAppViewer::initConfiguration() { const std::string& name = *itr; const std::string& value = *(++itr); - LLControlVariable* c = gSettings[sGlobalSettingsName]->getControl(name); + LLControlVariable* c = settings[sGlobalSettingsName]->getControl(name); if(c) { c->setValue(value, false); @@ -3213,12 +3212,15 @@ void LLAppViewer::saveFinalSnapshot() gSavedSettings.setBOOL("ShowParcelOwners", FALSE); idle(); - std::string snap_filename = gDirUtilp->getLindenUserDir(); - snap_filename += gDirUtilp->getDirDelimiter(); - snap_filename += SCREEN_LAST_FILENAME; - // use full pixel dimensions of viewer window (not post-scale dimensions) - gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE); - mSavedFinalSnapshot = TRUE; + std::string snap_filename = gDirUtilp->getLindenUserDir(true); + if (!snap_filename.empty()) + { + snap_filename += gDirUtilp->getDirDelimiter(); + snap_filename += SCREEN_LAST_FILENAME; + // use full pixel dimensions of viewer window (not post-scale dimensions) + gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE); + mSavedFinalSnapshot = TRUE; + } } } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 14a39a6f9..933d4150a 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -33,7 +33,8 @@ #ifndef LL_LLAPPVIEWER_H #define LL_LLAPPVIEWER_H -#include "llsys.h" // LLOSInfo +#include "llsys.h" // LLOSInfo +#include "llviewercontrol.h" // settings_map_type class LLTextureCache; class LLImageDecodeThread; @@ -140,11 +141,12 @@ public: // Load settings from the location specified by loction_key. // Key availale and rules for loading, are specified in // 'app_settings/settings_files.xml' - bool loadSettingsFromDirectory(const std::string& location_key, - bool set_defaults = false); + bool loadSettingsFromDirectory(AIReadAccess const& settings_r, + std::string const& location_key, + bool set_defaults = false); - std::string getSettingsFilename(const std::string& location_key, - const std::string& file); + std::string getSettingsFilename(std::string const& location_key, + std::string const& file); // For thread debugging. // llstartup needs to control init. diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index bb9d61394..a19ad5658 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -139,6 +139,7 @@ int main( int argc, char **argv ) } delete viewer_app_ptr; viewer_app_ptr = NULL; + return 0; } diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 67fc17d28..b7bb39a74 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -119,6 +119,7 @@ int main( int argc, char **argv ) } delete viewer_app_ptr; viewer_app_ptr = NULL; + return 0; } diff --git a/indra/newview/llconsole.cpp b/indra/newview/llconsole.cpp index 4a0647b8b..937ccec24 100644 --- a/indra/newview/llconsole.cpp +++ b/indra/newview/llconsole.cpp @@ -68,8 +68,7 @@ LLConsole::LLConsole(const std::string& name, const LLRect &rect, mFadeTime(persist_time - FADE_DURATION), mFont(LLFontGL::getFontSansSerif()), mConsoleWidth(0), - mConsoleHeight(0), - mQueueMutex(NULL) + mConsoleHeight(0) { mTimer.reset(); diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index b3cff3315..9614f639d 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -252,12 +252,10 @@ BOOL LLFeatureManager::loadFeatureTables() mTableVersion = version; LLFeatureList *flp = NULL; - while (!file.eof() && file.good()) + while (file >> name) { char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - file >> name; - if (name.substr(0,2) == "//") { // This is a comment. @@ -265,13 +263,6 @@ BOOL LLFeatureManager::loadFeatureTables() continue; } - if (name.empty()) - { - // This is a blank line - file.getline(buffer, MAX_STRING); - continue; - } - if (name == "list") { if (flp) diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 043de9c23..ed4e378e3 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -275,7 +275,7 @@ LLFloaterAbout::LLFloaterAbout() // TODO: Implement media plugin version query - support.append("Qt Webkit Version: 4.7.1 "); + support.append("Qt Webkit Version: 4.7.1 (version number hard-coded)"); support.append("\n"); if (gPacketsIn > 0) diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp old mode 100755 new mode 100644 diff --git a/indra/newview/llfloatersellland.h b/indra/newview/llfloatersellland.h old mode 100755 new mode 100644 diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index 7e0557d17..2d7ce1da4 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -104,7 +104,7 @@ BOOL LLFloaterSettingsDebug::postBuild() void LLFloaterSettingsDebug::draw() { LLComboBox* settings_combo = getChild("settings_combo"); - LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); + LLControlVariable* controlp = static_cast(settings_combo->getCurrentUserdata()); updateControl(controlp ? controlp->getCOAActive() : NULL); LLFloater::draw(); @@ -127,8 +127,8 @@ void LLFloaterSettingsDebug::show(void*) void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl, void* user_data) { LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data; - LLComboBox* combo_box = (LLComboBox*)ctrl; - LLControlVariable* controlp = (LLControlVariable*)combo_box->getCurrentUserdata(); + LLComboBox* combo_box = static_cast(ctrl); + LLControlVariable* controlp = static_cast(combo_box->getCurrentUserdata()); floaterp->updateControl(controlp ? controlp->getCOAActive() : NULL); } @@ -139,7 +139,7 @@ void LLFloaterSettingsDebug::onCommitSettings(LLUICtrl* ctrl, void* user_data) LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data; LLComboBox* settings_combo = floaterp->getChild("settings_combo"); - LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); + LLControlVariable* controlp = static_cast(settings_combo->getCurrentUserdata()); controlp = controlp ? controlp->getCOAActive() : NULL; if(!controlp)//Uh oh! return; diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 71b4e638d..9e4f9e24b 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -97,7 +97,7 @@ public: virtual void move( LLFolderViewEventListener* parent_listener ) = 0; virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; - virtual void cutToClipboard() = 0; + virtual BOOL cutToClipboard() const = 0; virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard() = 0; virtual void pasteLinkFromClipboard() = 0; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d96aa3bbc..31743deb3 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1347,7 +1347,7 @@ void LLIMMgr::saveIgnoreGroup() { // llinfos << "saving ignore_groups.xml" << llendl; - std::string user_dir = gDirUtilp->getLindenUserDir(); + std::string user_dir = gDirUtilp->getLindenUserDir(true); if (!user_dir.empty()) { std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "ignore_groups.xml"); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h old mode 100755 new mode 100644 index dcadc2781..a3108d653 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -232,7 +232,7 @@ public: virtual void move(LLFolderViewEventListener* new_parent_bridge) {} virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const { return FALSE; } - virtual void cutToClipboard() {} + virtual BOOL cutToClipboard() const { return FALSE; } virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual void pasteFromClipboard() {} diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 40b1c6414..dca58d5f4 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -264,7 +264,7 @@ LLMuteList::~LLMuteList() // If we quit from the login screen we will not have an SL account // name. Don't try to save, otherwise we'll dump a file in // C:\Program Files\SecondLife\ JC - std::string user_dir = gDirUtilp->getLindenUserDir(); + std::string user_dir = gDirUtilp->getLindenUserDir(true); if (!user_dir.empty()) { std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 453cf7fab..364fb1c44 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -72,7 +72,7 @@ LLNameListCtrl::~LLNameListCtrl() // public BOOL LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, - BOOL enabled, std::string& suffix) + BOOL enabled, std::string const& suffix) { //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 1b7795ddf..4485faedf 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -58,7 +58,7 @@ public: // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. BOOL addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, - BOOL enabled = TRUE, std::string& suffix = LLStringUtil::null); + BOOL enabled = TRUE, std::string const& suffix = LLStringUtil::null); BOOL addNameItem(LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM); virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); diff --git a/indra/newview/llpanelinventory.cpp b/indra/newview/llpanelinventory.cpp index 38521e7ab..38c90783b 100644 --- a/indra/newview/llpanelinventory.cpp +++ b/indra/newview/llpanelinventory.cpp @@ -144,7 +144,7 @@ public: virtual void move(LLFolderViewEventListener* parent_listener); virtual BOOL isItemCopyable() const; virtual BOOL copyToClipboard() const; - virtual void cutToClipboard(); + virtual BOOL cutToClipboard() const; virtual BOOL isClipboardPasteable() const; virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); @@ -596,8 +596,9 @@ BOOL LLTaskInvFVBridge::copyToClipboard() const return FALSE; } -void LLTaskInvFVBridge::cutToClipboard() +BOOL LLTaskInvFVBridge::cutToClipboard() const { + return FALSE; } BOOL LLTaskInvFVBridge::isClipboardPasteable() const diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index ece744e5e..7d7d65a35 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -911,20 +911,11 @@ void LLPanelLogin::loadLoginPage() std::string version = llformat("%d.%d.%d (%d)", LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VERSION_BUILD); - char* curl_channel = curl_escape(LL_CHANNEL, 0); - - char* curl_version = curl_escape(version.c_str(), 0); - - oStr << "&channel=" << curl_channel; - oStr << "&version=" << curl_version; - - curl_free(curl_channel); - curl_free(curl_version); + oStr << "&channel=" << LLWeb::curlEscape(LL_CHANNEL); + oStr << "&version=" << LLWeb::curlEscape(version); // Grid - char* curl_grid = curl_escape(LLViewerLogin::getInstance()->getGridLabel().c_str(), 0); - oStr << "&grid=" << curl_grid; - curl_free(curl_grid); + oStr << "&grid=" << LLWeb::curlEscape(LLViewerLogin::getInstance()->getGridLabel()); if (gHippoGridManager->getConnectedGrid()->isSecondLife()) { // find second life grid from login URI @@ -938,9 +929,7 @@ void LLPanelLogin::loadLoginPage() i = tmp.rfind('/'); if (i != std::string::npos) { tmp = tmp.substr(i+1); - char* curl_grid = curl_escape(tmp.c_str(), 0); - oStr << "&grid=" << curl_grid; - curl_free(curl_grid); + oStr << "&grid=" << LLWeb::curlEscape(tmp); } } } @@ -997,13 +986,11 @@ void LLPanelLogin::loadLoginPage() lastname = gSavedSettings.getString("LastName"); } - char* curl_region = curl_escape(region.c_str(), 0); + std::string curl_region = LLWeb::curlEscape(region); oStr <<"firstname=" << firstname << "&lastname=" << lastname << "&location=" << location << "®ion=" << curl_region; - curl_free(curl_region); - if (!password.empty()) { oStr << "&password=" << password; diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 52d3f0b03..1ebe341bf 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -252,7 +252,7 @@ public: return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); } }; - typedef boost::filter_iterator valid_root_iterator; + typedef boost::filter_iterator valid_root_iterator; valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); } valid_root_iterator valid_root_end() { return valid_root_iterator(mList.end(), mList.end()); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index dd42f2eeb..e08bc301a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -985,7 +985,7 @@ bool idle_startup() ); // Overwrite default user settings with user settings - LLAppViewer::instance()->loadSettingsFromDirectory("Account"); + LLAppViewer::instance()->loadSettingsFromDirectory(AIReadAccess(gSettings), "Account"); // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation // and startup time is close enough if we don't have a real value. @@ -1890,6 +1890,10 @@ bool idle_startup() gLLWindEnabled = gSavedSettings.getBOOL("WindEnabled"); set_startup_status(0.40f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); + + // Initialize the rest of the world. + gViewerWindow->initWorldUI_postLogin(); + display_startup(); // We should have an agent id by this point. llassert(!(gAgentID == LLUUID::null)); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 5c27e365a..c37add97a 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -743,9 +743,6 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted) LLTextureCache::LLTextureCache(bool threaded) : LLWorkerThread("TextureCache", threaded), - mWorkersMutex(NULL), - mHeaderMutex(NULL), - mListMutex(NULL), mHeaderAPRFile(NULL), mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called. mTexturesSizeTotal(0), @@ -1426,7 +1423,7 @@ void LLTextureCache::readHeaderCache() { // Special case: cache size was reduced, need to remove entries // Note: After we prune entries, we will call this again and create the LRU - U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; + U32 entries_to_purge = (num_entries - empty_entries) - sCacheMaxEntries; llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; // We can exit the following loop with the given condition, since if we'd reach the end of the lru set we'd have: // purge_list.size() = lru.size() = num_entries - empty_entries = entries_to_purge + sCacheMaxEntries >= entries_to_purge diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 45ec5e211..3a4b1f25e 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -143,9 +143,6 @@ protected: std::string getTextureFileName(const LLUUID& id); void addCompleted(Responder* responder, bool success); -protected: - //void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; } - private: void setDirNames(ELLPath location); void readHeaderCache(); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 0655b509e..cd74d3d73 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -425,7 +425,7 @@ class SGHostBlackList{ static void lock() { if (!sMutex) - sMutex = new LLMutex(0); + sMutex = new LLMutex; sMutex->lock(); } @@ -767,7 +767,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mRetryAttempt(0), mActiveCount(0), mGetStatus(0), - mWorkMutex(NULL), mFirstPacket(0), mLastPacket(-1), mTotalPackets(0), @@ -1943,8 +1942,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mDebugPause(FALSE), mPacketCount(0), mBadPacketCount(0), - mQueueMutex(getAPRPool()), - mNetworkQueueMutex(getAPRPool()), mTextureCache(cache), mImageDecodeThread(imagedecodethread), mTextureBandwidth(0), diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp old mode 100755 new mode 100644 diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h old mode 100755 new mode 100644 diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index d4bb75913..501dfe29b 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -36,6 +36,7 @@ #include "lltranslate.h" #include "llui.h" #include "llversionviewer.h" +#include "llweb.h" // #include "llviewercontrol.h" @@ -79,7 +80,7 @@ void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std //static void LLTranslate::getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &mesg) { - std::string escaped_mesg = curl_escape(mesg.c_str(), mesg.size()); + std::string escaped_mesg = LLWeb::curlEscape(mesg); translateUrl = m_GoogleURL + escaped_mesg + m_GoogleLangSpec diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp index 6930d8ac2..a93cc2ff7 100644 --- a/indra/newview/llurlhistory.cpp +++ b/indra/newview/llurlhistory.cpp @@ -74,7 +74,7 @@ bool LLURLHistory::loadFile(const std::string& filename) // static bool LLURLHistory::saveFile(const std::string& filename) { - std::string temp_str = gDirUtilp->getLindenUserDir(); + std::string temp_str = gDirUtilp->getLindenUserDir(true); if( temp_str.empty() ) { llwarns << "Can't save. No user directory set." << llendl; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 22609c938..23c9535fa 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -75,6 +75,7 @@ #include "llnetmap.h" #include "llrender.h" #include "llfloaterchat.h" +#include "aithreadsafe.h" #include "llviewerobjectlist.h" #include "lldrawpoolbump.h" #include "emeraldboobutils.h" @@ -83,8 +84,7 @@ BOOL gHackGodmode = FALSE; #endif - -std::map gSettings; +AITHREADSAFE(settings_map_type, gSettings,); LLControlGroup gSavedSettings; // saved at end of session LLControlGroup gSavedPerAccountSettings; // saved at end of session LLControlGroup gColors; // read-only diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index 9c2e112c9..8835146ad 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -36,6 +36,7 @@ #include #include "llcontrol.h" #include "lluictrl.h" +#include "aithreadsafe.h" // Enabled this definition to compile a 'hacked' viewer that // allows a hacked godmode to be toggled on and off. @@ -48,7 +49,8 @@ extern BOOL gHackGodmode; //setting variables are declared in this function void settings_setup_listeners(); -extern std::map gSettings; +typedef std::map settings_map_type; +extern AIThreadSafe gSettings; // for the graphics settings void create_graphics_group(LLControlGroup& group); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b75c3345e..873e6d1ae 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6643,7 +6643,7 @@ class LLFloaterVisible : public view_listener_t } else if (floater_name == "teleport history") { - new_value = gFloaterTeleportHistory->getVisible(); + new_value = (gFloaterTeleportHistory && gFloaterTeleportHistory->getVisible()); } else if (floater_name == "im") { diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp old mode 100755 new mode 100644 diff --git a/indra/newview/llviewerobjectbackup.h b/indra/newview/llviewerobjectbackup.h old mode 100755 new mode 100644 diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index 2921dd583..85eaabee9 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -164,7 +164,7 @@ #include "llinstantmessage.h" #include "llinvite.h" //#include "llloginflags.h" -#include "llmail.h" +//#include "llmail.h" #include "llmessagethrottle.h" #include "llnamevalue.h" #include "llpacketack.h" diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index bcd34fd7d..a82fdb3d5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1912,7 +1912,8 @@ void LLViewerWindow::initWorldUI() S32 width = mRootView->getRect().getWidth(); LLRect full_window(0, height, width, 0); - if ( gBottomPanel == NULL ) // Don't re-enter if objects are alreay created + // Don't re-enter if objects are alreay created + if (gBottomPanel == NULL) { // panel containing chatbar, toolbar, and overlay, over floaters gBottomPanel = new LLBottomPanel(mRootView->getRect()); @@ -1925,6 +1926,57 @@ void LLViewerWindow::initWorldUI() gIMMgr = LLIMMgr::getInstance(); + // + // Tools for building + // + + init_menus(); + + // Toolbox floater + gFloaterTools = new LLFloaterTools(); + gFloaterTools->setVisible(FALSE); + } + + if ( gHUDView == NULL ) + { + LLRect hud_rect = full_window; + hud_rect.mBottom += 50; + if (gMenuBarView) + { + hud_rect.mTop -= gMenuBarView->getRect().getHeight(); + } + gHUDView = new LLHUDView(hud_rect); + // put behind everything else in the UI + mRootView->addChildAtEnd(gHUDView); + } +} + +// initWorldUI that wasn't before logging in. Some of this may require the access the 'LindenUserDir'. +void LLViewerWindow::initWorldUI_postLogin() +{ + S32 height = mRootView->getRect().getHeight(); + S32 width = mRootView->getRect().getWidth(); + LLRect full_window(0, height, width, 0); + + // Don't re-enter if objects are alreay created. + if (!gStatusBar) + { + // Status bar + S32 menu_bar_height = gMenuBarView->getRect().getHeight(); + LLRect root_rect = getRootView()->getRect(); + LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); + gStatusBar = new LLStatusBar(std::string("status"), status_rect); + gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + + gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); + gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); + // sync bg color with menu bar + gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); + getRootView()->addChild(gStatusBar); + + // Menu holder appears on top to get first pass at all mouse events + getRootView()->sendChildToFront(gMenuHolder); + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) { LLFloaterChat::getInstance(LLSD())->loadHistory(); @@ -1950,47 +2002,7 @@ void LLViewerWindow::initWorldUI() gFloaterTeleportHistory = new LLFloaterTeleportHistory(); gFloaterTeleportHistory->setVisible(FALSE); - // - // Tools for building - // - - // Toolbox floater - init_menus(); - - gFloaterTools = new LLFloaterTools(); - gFloaterTools->setVisible(FALSE); - - // Status bar - S32 menu_bar_height = gMenuBarView->getRect().getHeight(); - LLRect root_rect = getRootView()->getRect(); - LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); - gStatusBar = new LLStatusBar(std::string("status"), status_rect); - gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); - - gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); - gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); - // sync bg color with menu bar - gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); - LLFloaterChatterBox::createInstance(LLSD()); - - getRootView()->addChild(gStatusBar); - - // menu holder appears on top to get first pass at all mouse events - getRootView()->sendChildToFront(gMenuHolder); - } - - if ( gHUDView == NULL ) - { - LLRect hud_rect = full_window; - hud_rect.mBottom += 50; - if (gMenuBarView) - { - hud_rect.mTop -= gMenuBarView->getRect().getHeight(); - } - gHUDView = new LLHUDView(hud_rect); - // put behind everything else in the UI - mRootView->addChildAtEnd(gHUDView); } } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 538a6f188..21867f7eb 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -144,6 +144,7 @@ public: void adjustRectanglesForFirstUse(const LLRect& window); void adjustControlRectanglesForFirstUse(const LLRect& window); void initWorldUI(); + void initWorldUI_postLogin(); // // LLWindowCallback interface implementation diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index eca5594a5..79e8fc535 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1781,7 +1781,7 @@ void LLVoiceClient::stateMachine() if(!mSocket) { - mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + mSocket = LLSocket::create(LLSocket::STREAM_TCP); } mConnected = mSocket->blockingConnect(mDaemonHost); diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index 330bc8a39..9af050c4c 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -184,8 +184,8 @@ void LLWatchdog::init(killer_event_callback func) mKillerCallback = func; if(!mSuspectsAccessMutex && !mTimer) { - mSuspectsAccessMutex = new LLMutex(NULL); - mTimer = new LLWatchdogTimerThread(); + mSuspectsAccessMutex = new LLMutex; + mTimer = new LLWatchdogTimerThread; mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000); mLastClockCount = LLTimer::getTotalTime(); diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 848c8137f..682079249 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -143,10 +143,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) void LLWaterParamManager::loadPreset(const std::string & name,bool propagate) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(name); escaped_filename += ".xml"; @@ -199,10 +196,7 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate) void LLWaterParamManager::savePreset(const std::string & name) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(name); escaped_filename += ".xml"; @@ -415,10 +409,7 @@ bool LLWaterParamManager::removeParamSet(const std::string& name, bool delete_fr std::string path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", "")); // use full curl escaped name - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_name(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_name = LLWeb::curlEscape(name); gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml"); } diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 7a7c80fdf..b57e4bcc8 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -68,6 +68,20 @@ void LLWeb::loadURLExternal(const std::string& url) } +// static +std::string LLWeb::curlEscape(const std::string& url) +{ + std::stringstream escaped_url; + for (std::string::const_iterator iter = url.begin(); iter != url.end(); ++iter) + { + if (std::isalnum(*iter)) + escaped_url << *iter; + else + escaped_url << '%' << std::hex << std::setfill('0') << std::setw(2) << std::uppercase << (int)*iter; + } + return escaped_url.str(); +} + // static std::string LLWeb::escapeURL(const std::string& url) { diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 278821bac..8dd13ffcb 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -51,6 +51,9 @@ public: // Loads unescaped url in external browser. static void loadURLExternal(const std::string& url); + // Behaves like the old curl_escape. + static std::string curlEscape(const std::string& url); + // Returns escaped (eg, " " to "%20") url static std::string escapeURL(const std::string& url); diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp index 2abf9d45a..577d1edc1 100644 --- a/indra/newview/llwldaycycle.cpp +++ b/indra/newview/llwldaycycle.cpp @@ -35,6 +35,7 @@ #include "llwldaycycle.h" #include "llsdserialize.h" #include "llwlparammanager.h" +#include "llweb.h" #include "llviewerwindow.h" @@ -57,10 +58,7 @@ void LLWLDayCycle::loadDayCycle(const std::string & fileName) mTimeMap.clear(); // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(fileName.c_str(), fileName.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(fileName); escaped_filename += ".xml"; @@ -125,10 +123,7 @@ void LLWLDayCycle::saveDayCycle(const std::string & fileName) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(fileName.c_str(), fileName.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(fileName); escaped_filename += ".xml"; diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index dfe921667..bb41f9aac 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -187,10 +187,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(name); escaped_filename += ".xml"; @@ -244,10 +241,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate) void LLWLParamManager::savePreset(const std::string & name) { // bugfix for SL-46920: preventing filenames that break stuff. - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_filename(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_filename = LLWeb::curlEscape(name); escaped_filename += ".xml"; @@ -531,10 +525,7 @@ bool LLWLParamManager::removeParamSet(const std::string& name, bool delete_from_ std::string path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", "")); // use full curl escaped name - char * curl_str = curl_escape(name.c_str(), name.size()); - std::string escaped_name(curl_str); - curl_free(curl_str); - curl_str = NULL; + std::string escaped_name = LLWeb::curlEscape(name); gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml"); } diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 0f5cc88ad..3f93a7ef8 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -389,5 +389,6 @@ + diff --git a/indra/newview/skins/default/xui/en-us/mime_types.xml b/indra/newview/skins/default/xui/en-us/mime_types.xml deleted file mode 100644 index 4a7a6e17a..000000000 --- a/indra/newview/skins/default/xui/en-us/mime_types.xml +++ /dev/null @@ -1,445 +0,0 @@ - - - - (Unknown) - - - none - - - media_plugin_webkit - - - - - icn_media_web.tga - - - text/html - - - This location has Web content - - - Show Web content - - - true - - - false - - - - - - video/* - - - icn_media_movie.tga - - - There is a movie to play here - - - Play movie - - - false - - - true - - - - - - icn_media_web.tga - - - image/* - - - There is an image at this location - - - View this location's image - - - false - - - false - - - - - - icn_media_web.tga - - - audio/* - - - There is audio at this location - - - Play this location's audio - - - false - - - true - - - - - - movie - - - media_plugin_quicktime - - - - - - none - - - media_plugin_quicktime - - - - - - none - - - - - - audio - - - - - - movie - - - - - - image - - - - - - movie - - - media_plugin_quicktime - - - - - - web - - - - - - audio - - - - - - image - - - - - - image - - - - - - image - - - - - - movie - - - media_plugin_quicktime - - - - - - web - - - - - - image - - - - - - audio - - - media_plugin_quicktime - - - - - - audio - - - media_plugin_quicktime - - - - - - audio - - - media_plugin_quicktime - - - - - - audio - - - media_plugin_quicktime - - - - - - image - - - media_plugin_webkit - - - - - - image - - - media_plugin_webkit - - - - - - image - - - media_plugin_webkit - - - - - - image - - - media_plugin_webkit - - - - - - image - - - media_plugin_webkit - - - - - - image - - - media_plugin_webkit - - - - - - web - - - media_plugin_webkit - - - - - - text - - - media_plugin_webkit - - - - - - text - - - media_plugin_webkit - - - - - - movie - - - media_plugin_quicktime - - - - - - movie - - - media_plugin_quicktime - - - - - - movie - - - media_plugin_quicktime - - - - - - movie - - - media_plugin_quicktime - - - - - - movie - - - media_plugin_quicktime - - - - - - movie - - - media_plugin_quicktime - - - diff --git a/indra/newview/skins/default/xui/en-us/mime_types_linux.xml b/indra/newview/skins/default/xui/en-us/mime_types_linux.xml index f04992ade..e95b371d0 100644 --- a/indra/newview/skins/default/xui/en-us/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en-us/mime_types_linux.xml @@ -175,8 +175,8 @@ movie - media_plugin_gstreamer - + media_plugin_gstreamer + movie @@ -384,8 +384,8 @@ web - media_plugin_webkit - + media_plugin_webkit + diff --git a/indra/newview/skins/default/xui/en-us/mime_types_mac.xml b/indra/newview/skins/default/xui/en-us/mime_types_mac.xml index 5b66271a5..7931e55c0 100644 --- a/indra/newview/skins/default/xui/en-us/mime_types_mac.xml +++ b/indra/newview/skins/default/xui/en-us/mime_types_mac.xml @@ -175,8 +175,8 @@ movie - media_plugin_quicktime - + media_plugin_quicktime + movie @@ -384,8 +384,8 @@ web - media_plugin_webkit - + media_plugin_webkit + diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 5c31afb64..750c9faa5 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -43,7 +43,7 @@ class LLControlGroupReader_Test : public LLControlGroupReader public: LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {} - virtual std::string getString(const std::string& name) + virtual std::string getString(const std::string& name) const { return ""; } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 24d48c9f8..9ca3b4704 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -122,6 +122,8 @@ class ViewerManifest(LLManifest): def buildtype(self): return self.args['buildtype'] + def standalone(self): + return self.args['standalone'] == "ON" def grid(self): return self.args['grid'] def channel(self): @@ -759,19 +761,9 @@ class Linux_i686Manifest(LinuxManifest): def construct(self): super(Linux_i686Manifest, self).construct() - # install either the libllkdu we just built, or a prebuilt one, in - # decreasing order of preference. for linux package, this goes to bin/ - #~ try: - #~ self.path(self.find_existing_file('../llkdu/libllkdu.so', - #~ '../../libraries/i686-linux/lib_release_client/libllkdu.so'), - #~ dst='bin/libllkdu.so') - #~ # keep this one to preserve syntax, open source mangling removes previous lines - #~ pass - #~ except: - #~ print "Skipping libllkdu.so - not found" - #~ pass + self.path("../llcommon/libllcommon.so", "lib/libllcommon.so") - if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): + if (not self.standalone()) and self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): try: self.path("libkdu_v42R.so", "libkdu.so") @@ -815,12 +807,55 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxsdk.so") self.end_prefix("lib") + class Linux_x86_64Manifest(LinuxManifest): def construct(self): super(Linux_x86_64Manifest, self).construct() - # support file for valgrind debug tool - self.path("secondlife-i686.supp") + self.path("../llcommon/libllcommon.so", "lib64/libllcommon.so") + + if (not self.standalone()) and self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): + self.path("libapr-1.so.0") + self.path("libaprutil-1.so.0") + self.path("libdb-4.2.so") + self.path("libcrypto.so.0.9.8") + self.path("libexpat.so.1") + self.path("libhunspell-1.2.so.0.0.0", "libhunspell-1.2.so.0") + self.path("libssl.so.0.9.8") + self.path("libuuid.so", "libuuid.so.1") + self.path("libSDL-1.2.so.0") + self.path("libELFIO.so") + self.path("libjpeg.so.7") + self.path("libpng12.so.0") + self.path("libopenjpeg.so.2") + self.path("libxml2.so.2") + #self.path("libz.so.1") #not needed + + # OpenAL + self.path("libopenal.so.1") + self.path("libalut.so.0") + + self.end_prefix("lib64") + + # Vivox runtimes and libs + if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): + self.path("SLVoice") + self.end_prefix("bin") + + if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"): + #self.path("libalut.so") + self.path("libortp.so") + self.path("libvivoxsdk.so") + self.end_prefix("lib32") + + # 32bit libs needed for voice + if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): + self.path("libalut.so") + self.path("libidn.so.11") + self.path("libopenal.so.1") + # self.path("libortp.so") + self.path("libuuid.so.1") + self.end_prefix("lib32") if __name__ == "__main__": main() diff --git a/indra/test/llrandom_tut.cpp b/indra/test/llrandom_tut.cpp old mode 100755 new mode 100644 diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp old mode 100755 new mode 100644 diff --git a/indra/test/llsdmessagereader_tut.cpp b/indra/test/llsdmessagereader_tut.cpp old mode 100755 new mode 100644 diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp index 5b33d0272..9fecc2f90 100644 --- a/indra/test/lltemplatemessagebuilder_tut.cpp +++ b/indra/test/lltemplatemessagebuilder_tut.cpp @@ -35,7 +35,6 @@ #include "linden_common.h" #include "lltut.h" -#include "llapr.h" #include "llmessagetemplate.h" #include "llquaternion.h" #include "lltemplatemessagebuilder.h" @@ -59,7 +58,6 @@ namespace tut static bool init = false; if(! init) { - ll_init_apr(); const F32 circuit_heartbeat_interval=5; const F32 circuit_timeout=100; diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index 3fede2608..694db5213 100644 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -35,7 +35,6 @@ #include "linden_common.h" #include "lltut.h" -#include "llapr.h" #include "llmessageconfig.h" #include "llsdserialize.h" #include "llversionserver.h" @@ -68,7 +67,6 @@ namespace tut static bool init = false; if(!init) { - ll_init_apr(); //init_prehash_data(); init = true; } diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 8e1376ddc..d8f00c602 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -43,8 +43,8 @@ #include "linden_common.h" #include "llerrorcontrol.h" #include "lltut.h" +#include "aiaprpool.h" -#include "apr_pools.h" #include "apr_getopt.h" extern void ll_init_apr(); @@ -250,17 +250,12 @@ int main(int argc, char **argv) ctype_workaround(); #endif - ll_init_apr(); - apr_pool_t* pool = NULL; - if(APR_SUCCESS != apr_pool_create(&pool, NULL)) - { - std::cerr << "Unable to initialize pool" << std::endl; - return 1; - } + AIAPRPool pool; + pool.create(); apr_getopt_t* os = NULL; - if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv)) + if(APR_SUCCESS != apr_getopt_init(&os, pool(), argc, argv)) { - std::cerr << "Unable to pool" << std::endl; + std::cerr << "Unable to initialize the arguments for parsing by apr_getopt()." << std::endl; return 1; } @@ -362,6 +357,5 @@ int main(int argc, char **argv) s.close(); } - apr_terminate(); return 0; } diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/bookmarks.txt b/indra/test_apps/llplugintest/bookmarks.txt old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/demo_media_plugin.cpp b/indra/test_apps/llplugintest/demo_media_plugin.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/demo_media_plugin_2.cpp b/indra/test_apps/llplugintest/demo_media_plugin_2.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/demo_plugin.cpp b/indra/test_apps/llplugintest/demo_plugin.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/media_mappings.txt b/indra/test_apps/llplugintest/media_mappings.txt old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/media_plugin_test.cpp b/indra/test_apps/llplugintest/media_plugin_test.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/media_simple_test.cpp b/indra/test_apps/llplugintest/media_simple_test.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/plugin_host.cpp b/indra/test_apps/llplugintest/plugin_host.cpp old mode 100755 new mode 100644 diff --git a/indra/test_apps/llplugintest/plugin_process_launcher.cpp b/indra/test_apps/llplugintest/plugin_process_launcher.cpp old mode 100755 new mode 100644 diff --git a/install.xml b/install.xml index eb4d4909f..d9763c189 100644 --- a/install.xml +++ b/install.xml @@ -162,26 +162,12 @@ artwork packages - darwin + common md5sum - 5e047437d73d1017bf270a6c6e936f23 + a2cde4f24bdcc260b661e139846b8acd url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/artwork-common-20090415.tar.bz2 - - linux - - md5sum - 5e047437d73d1017bf270a6c6e936f23 - url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/artwork-common-20090415.tar.bz2 - - windows - - md5sum - 5e047437d73d1017bf270a6c6e936f23 - url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/artwork-common-20090415.tar.bz2 + http://imprudenceviewer.org/download/libs/imprudence-artwork-20101026.tar.bz2 @@ -374,39 +360,6 @@ - fmod - - copyright - FMOD Sound System, copyright (C) Firelight Technologies Pty, Ltd., 1994-2006. - description - Audio engine and mp3 stream decoder . - license - fmod - packages - - darwin - - md5sum - c7e317bec481b7efa2a0319e163dcc65 - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/fmod-3.75-darwin-20080818.tar.bz2 - - linux - - md5sum - abd2b4ba4ac993f19d82804af387eb7c - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/fmod-3.75-linux-20080818.tar.bz2 - - windows - - md5sum - 1a55dec2907821f5f785648a660126c3 - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/fmod-3.75-windows-20080611.tar.bz2 - - - fontconfig license @@ -1015,35 +968,6 @@ anguage Infrstructure (CLI) international standard - mysql - - license - gpl - packages - - darwin - - md5sum - df27f2db244ea2762759a06cd75ada4e - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/mysql-darwin-20080812.tar.bz2 - - linux - - md5sum - cc86b4cc858655e23704d1168325d7b9 - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/mysqlclient-linux-20090320.tar.bz2 - - windows - - md5sum - 98bac06680dca907e783d8dd4aa9edde - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/mysql-windows-20080804.tar.bz2 - - - ndofdev copyright @@ -1219,58 +1143,6 @@ anguage Infrstructure (CLI) international standard - quicktime - - copyright - Copyright (C) 1990-2007 by Apple Computer, Inc., all rights reserved. - description - Separate download. Used to play in-world video clips on a prim. - license - quicktime - packages - - windows - - md5sum - be45825cc14ede53790ac93c58307dcb - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/quicktime-sdk-windows-7.3-20091110.tar.bz2 - - - - smartheap - - copyright - Copyright (C) 1991-2000 Compuware Corporation. All Rights Reserved. - description - Memory Management Library - license - smartheap - packages - - darwin - - md5sum - f54131b5f228e805c64c2e4e6c96579a - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/smartheap-6.0.2-darwin-20080610.tar.bz2 - - linux - - md5sum - 499208522bf7d7843e1d014d64214e06 - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/smartheap-6.0.2-linux-20080610.tar.bz2 - - windows - - md5sum - 78fd47017f21d11eae43bca3e38a3e1e - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/smartheap-6.0.2-windows-20080611.tar.bz2 - - - tut copyright @@ -1331,6 +1203,13 @@ anguage Infrstructure (CLI) international standard url http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-2.1.3010.6270-linux-20090309.tar.bz2 + linux64 + + md5sum + 01573510dce7f380f44e561ef2f3dd9f + url + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-2.1.3010.6270-linux-20090309.tar.bz2 + windows md5sum @@ -1340,6 +1219,29 @@ anguage Infrstructure (CLI) international standard + 32bitcompatibilitylibs + + copyright + Copyrights: Libidn: Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Simon Josefsson. License GPL v3.0. + Freealut, libuuid, openal-soft: see copyright and license of the + according main packages. + + description + 32bit libraries needed for using voice + license + gpl + packages + + linux64 + + md5sum + cbaafc55fb8b14283541791e82f13462 + url + http://imprudenceviewer.org/download/libs/linux64-32bitcompatibilitylibs-20100903.tar.bz2 + + + xmlrpc-epi copyright diff --git a/scripts/install.py b/scripts/install.py index 85818bc9a..e53f664b4 100755 --- a/scripts/install.py +++ b/scripts/install.py @@ -535,24 +535,24 @@ windows/i686/vs/2003 -- specify a windows visual studio 2003 package""" platform, cache_dir)) to_install = [] + to_uninstall = [] #print "self._installed",self._installed for ifile in ifiles: if ifile.pkgname not in self._installed: to_install.append(ifile) elif ifile.url not in self._installed[ifile.pkgname].urls(): + to_uninstall.append(ifile.pkgname) to_install.append(ifile) elif ifile.md5sum != \ self._installed[ifile.pkgname].get_md5sum(ifile.url): - # *TODO: We may want to uninstall the old version too - # when we detect it is installed, but the md5 sum is - # different. + to_uninstall.append(ifile.pkgname) to_install.append(ifile) else: #print "Installation up to date:", # ifile.pkgname,ifile.platform_path pass #print "to_install",to_install - return to_install + return [to_install, to_uninstall] def _install(self, to_install, install_dir): for ifile in to_install: @@ -565,17 +565,43 @@ windows/i686/vs/2003 -- specify a windows visual studio 2003 package""" tar.extractall(path=install_dir) except AttributeError: _extractall(tar, path=install_dir) + symlinks = [] + if _get_platform() == 'linux' or _get_platform() == 'linux64': + first = 1 + for tfile in tar.getnames(): + if tfile.find('.so.') > 0: + LINK = re.sub(r'\.so\.[0-9.]*$', '.so', tfile) + link_name = install_dir + "/" + LINK + if not os.path.exists(link_name): + if first == 1: + first = 0 + print "Adding missing symlink(s) for package %s:" % ifile.filename + target = os.path.basename(tfile) + soname = os.popen("readelf -d \"%(install_dir)s/%(tfile)s\" %(stderr_redirect)s" + " | grep SONAME | sed -e 's/.*\[//;s/\].*//'" % + {"install_dir": install_dir, "tfile": tfile, "stderr_redirect": ("2>/dev/null" if self._dryrun else "")}).read() + soname = soname.strip() + if soname: # not empty + tmpfname = os.path.dirname(LINK) + "/" + soname + if os.path.exists(install_dir + "/" + tmpfname): + target = soname + else: + print "WARNING: SONAME %s doesn't exist!" % tmpfname + if not self._dryrun: + os.symlink(target, link_name) + symlinks += [LINK] + print " %s --> %s" % (LINK, target) if ifile.pkgname in self._installed: self._installed[ifile.pkgname].add_files( ifile.url, - tar.getnames()) + tar.getnames() + symlinks) self._installed[ifile.pkgname].set_md5sum( ifile.url, ifile.md5sum) else: # *HACK: this understands the installed package syntax. definition = { ifile.url : - {'files': tar.getnames(), + {'files': tar.getnames() + symlinks, 'md5sum' : ifile.md5sum } } self._installed[ifile.pkgname] = InstalledPackage(definition) self._installed_changed = True @@ -595,12 +621,17 @@ windows/i686/vs/2003 -- specify a windows visual studio 2003 package""" cache_dir = os.path.realpath(cache_dir) _mkdir(install_dir) _mkdir(cache_dir) - to_install = self._build_ifiles(platform, cache_dir) + to_install_uninstall = self._build_ifiles(platform, cache_dir) + to_install = to_install_uninstall[0] + to_uninstall = to_install_uninstall[1] # Filter for files which we actually requested to install. to_install = [ifl for ifl in to_install if ifl.pkgname in installables] + to_uninstall = [ifl for ifl in to_uninstall if ifl in installables] for ifile in to_install: ifile.fetch_local() + if to_uninstall: + self.uninstall(to_uninstall, install_dir) self._install(to_install, install_dir) def do_install(self, installables, platform, install_dir, cache_dir=None, @@ -787,7 +818,7 @@ def _get_platform(): # TODO -- someday when install.py accepts a platform of the form # os/arch/compiler/compiler_version then we can replace the # 'linux64' platform with 'linux/x86_64/gcc/4.1' - this_platform = 'linux' + this_platform = 'linux64' return this_platform def _getuser():