summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llsingleton.h24
-rw-r--r--indra/llcommon/tests/llsingleton_test.cpp75
-rw-r--r--indra/llmessage/llcurl.cpp2
-rw-r--r--indra/llmessage/llproxy.cpp14
-rw-r--r--indra/llmessage/llproxy.h40
6 files changed, 132 insertions, 24 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index c755020a64..16e2a0e5c8 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -319,6 +319,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
"${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
+ LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 00757be277..2ce6a9d438 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -114,8 +114,7 @@ private:
~SingletonInstanceData()
{
- SingletonInstanceData& data = getData();
- if (data.mInitState != DELETED)
+ if (mInitState != DELETED)
{
deleteSingleton();
}
@@ -130,7 +129,26 @@ public:
data.mInitState = DELETED;
}
- // Can be used to control when the singleton is deleted. Not normally needed.
+ /**
+ * @brief Immediately delete the singleton.
+ *
+ * A subsequent call to LLProxy::getInstance() will construct a new
+ * instance of the class.
+ *
+ * LLSingletons are normally destroyed after main() has exited and the C++
+ * runtime is cleaning up statically-constructed objects. Some classes
+ * derived from LLSingleton have objects that are part of a runtime system
+ * that is terminated before main() exits. Calling the destructor of those
+ * objects after the termination of their respective systems can cause
+ * crashes and other problems during termination of the project. Using this
+ * method to destroy the singleton early can prevent these crashes.
+ *
+ * An example where this is needed is for a LLSingleton that has an APR
+ * object as a member and make APR calls on destruction. The APR system is
+ * shut down explicitly before main() exits. This causes a crash on exit.
+ * Using this method before the call to apr_terminate() and NOT calling
+ * getInstance() again will prevent the crash.
+ */
static void deleteSingleton()
{
delete getData().mSingletonInstance;
diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp
new file mode 100644
index 0000000000..2e8b83fa2c
--- /dev/null
+++ b/indra/llcommon/tests/llsingleton_test.cpp
@@ -0,0 +1,75 @@
+/**
+ * @file llprocessor_test.cpp
+ * @date 2010-06-01
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llsingleton.h"
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct singleton
+ {
+ // We need a class created with the LLSingleton template to test with.
+ class LLSingletonTest: public LLSingleton<LLSingletonTest>
+ {
+
+ };
+ };
+
+ typedef test_group<singleton> singleton_t;
+ typedef singleton_t::object singleton_object_t;
+ tut::singleton_t tut_singleton("LLSingleton");
+
+ template<> template<>
+ void singleton_object_t::test<1>()
+ {
+
+ }
+ template<> template<>
+ void singleton_object_t::test<2>()
+ {
+ LLSingletonTest* singleton_test = LLSingletonTest::getInstance();
+ ensure(singleton_test);
+ }
+ template<> template<>
+ void singleton_object_t::test<3>()
+ {
+ //Construct the instance
+ LLSingletonTest::getInstance();
+ ensure(LLSingletonTest::instanceExists());
+
+ //Delete the instance
+ LLSingletonTest::deleteSingleton();
+ ensure(LLSingletonTest::destroyed());
+ ensure(!LLSingletonTest::instanceExists());
+
+ //Construct it again.
+ LLSingletonTest* singleton_test = LLSingletonTest::getInstance();
+ ensure(singleton_test);
+ ensure(LLSingletonTest::instanceExists());
+ }
+}
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index bfdf49c74b..2d456b8f3f 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -499,7 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
setopt(CURLOPT_SSL_VERIFYHOST, 0);
- setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
+ setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
setoptString(CURLOPT_URL, url);
diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
index 3f4a6accbf..611a40579d 100644
--- a/indra/llmessage/llproxy.cpp
+++ b/indra/llmessage/llproxy.cpp
@@ -43,7 +43,7 @@
bool LLProxy::sUDPProxyEnabled = false;
// Some helpful TCP static functions.
-static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake
+static S32 tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake
static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host); // Open a TCP channel to a given host
static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel
@@ -88,7 +88,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
socks_auth_request.num_methods = 1; // Sending 1 method.
socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method.
- result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response));
+ result = tcp_blocking_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response));
if (result != APR_SUCCESS)
{
LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL;
@@ -98,7 +98,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE)
{
- LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL;
+ LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods." << LL_ENDL;
stopSOCKSProxy();
return SOCKS_NOT_ACCEPTABLE;
}
@@ -119,7 +119,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
authmethod_password_reply_t password_reply;
- result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply));
+ result = tcp_blocking_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply));
delete[] password_auth;
if (result != APR_SUCCESS)
@@ -151,7 +151,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
// "If the client is not in possession of the information at the time of the UDP ASSOCIATE,
// the client MUST use a port number and address of all zeros. RFC 1928"
- result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply));
+ result = tcp_blocking_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply));
if (result != APR_SUCCESS)
{
LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL;
@@ -214,12 +214,14 @@ S32 LLProxy::startSOCKSProxy(LLHost host)
{
status = proxyHandshake(mTCPProxy);
}
+
if (status == SOCKS_OK)
{
sUDPProxyEnabled = true;
}
else
{
+ // Shut down the proxy if any of the above steps failed.
stopSOCKSProxy();
}
return status;
@@ -474,7 +476,7 @@ void LLProxy::applyProxySettings(CURL* handle)
* @param maxinlen Maximum possible length of received data. Short reads are allowed.
* @return Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received.
*/
-static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen)
+static S32 tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen)
{
apr_socket_t* apr_socket = handle->getSocket();
apr_status_t rv = APR_SUCCESS;
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index 29e7e28567..f8478bda30 100644
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -36,7 +36,6 @@
#include <string>
// SOCKS error codes returned from the StartProxy method
-
#define SOCKS_OK 0
#define SOCKS_CONNECT_ERROR (-1)
#define SOCKS_NOT_PERMITTED (-2)
@@ -46,7 +45,6 @@
#define SOCKS_HOST_CONNECT_FAILED (-6)
#define SOCKS_INVALID_HOST (-7)
-
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
#endif
@@ -225,8 +223,9 @@ class LLProxy: public LLSingleton<LLProxy>
{
LOG_CLASS(LLProxy);
public:
- // METHODS THAT DO NOT LOCK mProxyMutex!
-
+ /*###########################################################################################
+ METHODS THAT DO NOT LOCK mProxyMutex!
+ ###########################################################################################*/
LLProxy();
// static check for enabled status for UDP packets
@@ -242,10 +241,13 @@ public:
// Get the SOCKS 5 TCP control channel address and port
LLHost getTCPProxy() const { return mTCPProxy; }
- // END OF NON-LOCKING METHODS
-
- // METHODS THAT DO LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ /*###########################################################################################
+ END OF NON-LOCKING METHODS
+ ###########################################################################################*/
+ /*###########################################################################################
+ METHODS THAT DO LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ ###########################################################################################*/
~LLProxy();
// Start a connection to the SOCKS 5 proxy
@@ -288,9 +290,11 @@ public:
std::string getSocksPwd() const;
std::string getSocksUser() const;
- // END OF LOCKING METHODS
+ /*###########################################################################################
+ END OF LOCKING METHODS
+ ###########################################################################################*/
private:
- // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort
+ // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort.
S32 proxyHandshake(LLHost proxy);
private:
@@ -302,7 +306,9 @@ private:
// Mutex to protect shared members in non-main thread calls to applyProxySettings()
mutable LLMutex mProxyMutex;
- // MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
+ /*###########################################################################################
+ MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
+ ###########################################################################################*/
// Is the UDP proxy enabled?
static bool sUDPProxyEnabled;
@@ -318,9 +324,13 @@ private:
// APR pool for the socket
apr_pool_t* mPool;
- // END OF UNSHARED MEMBERS
+ /*###########################################################################################
+ END OF UNSHARED MEMBERS
+ ###########################################################################################*/
- // MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
+ /*###########################################################################################
+ MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
+ ###########################################################################################*/
// HTTP proxy address and port
LLHost mHTTPProxy;
@@ -328,7 +338,7 @@ private:
// Currently selected HTTP proxy type. Can be web or socks.
LLHttpProxyType mProxyType;
- // SOCKS 5 auth method selected
+ // SOCKS 5 selected authentication method.
LLSocks5AuthType mAuthMethodSelected;
// SOCKS 5 username
@@ -336,7 +346,9 @@ private:
// SOCKS 5 password
std::string mSocksPassword;
- // END OF SHARED MEMBERS
+ /*###########################################################################################
+ END OF SHARED MEMBERS
+ ###########################################################################################*/
};
#endif