From ef490e308ccce8e6df85144784a0f4580f5ac6a1 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 5 Feb 2011 15:58:07 +0100 Subject: Introduces a LLThreadLocalData class that can be accessed through the static LLThread::tldata(). Currently this object contains two (public) thread-local objects: a LLAPRRootPool and a LLVolatileAPRPool. The first is the general memory pool used by this thread (and this thread alone), while the second is intended for short lived memory allocations (needed for APR). The advantages of not mixing those two is that the latter is used most frequently, and as a result of it's nature can be destroyed and reconstructed on a "regular" basis. This patch adds LLAPRPool (completely replacing the old one), which is a wrapper around apr_pool_t* and has complete thread-safity checking. Whenever an apr call requires memory for some resource, a memory pool in the form of an LLAPRPool object can be created with the same life-time as this resource; assuring clean up of the memory no sooner, but also not much later than the life-time of the resource that needs the memory. Many, many function calls and constructors had the pool parameter simply removed (it is no longer the concern of the developer, if you don't write code that actually does an libapr call then you are no longer bothered with memory pools at all). However, I kept the notion of short-lived and long-lived allocations alive (see my remark in the jira here: https://jira.secondlife.com/browse/STORM-864?focusedCommentId=235356&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-235356 which requires that the LLAPRFile API needs to allow the user to specify how long they think a file will stay open. By choosing 'short_lived' as default for the constructor that immediately opens a file, the number of instances where this needs to be specified is drastically reduced however (obviously, any automatic LLAPRFile is short lived). *** Addressed Boroondas remarks in https://codereview.secondlife.com/r/99/ regarding (doxygen) comments. This patch effectively only changes comments. Includes some 'merge' stuff that ended up in llvocache.cpp (while starting as a bug fix, now only resulting in a cleanup). *** Added comment 'The use of apr_pool_t is OK here'. Added this comment on every line where apr_pool_t is correctly being used. This should make it easier to spot (future) errors where someone started to use apr_pool_t; you can just grep all sources for 'apr_pool_t' and immediately see where it's being used while LLAPRPool should have been used. Note that merging this patch is very easy: If there are no other uses of apr_pool_t in the code (one grep) and it compiles, then it will work. *** Second Merge (needed to remove 'delete mCreationMutex' from LLImageDecodeThread::~LLImageDecodeThread). *** Added back #include . Apparently that is needed on libapr version 1.2.8., the version used by Linden Lab, for calls to apr_queue_*. This is a bug in libapr (we also include , that is fixed in (at least) 1.3.7. Note that 1.2.8 is VERY old. Even 1.3.x is old. *** License fixes (GPL -> LGPL). And typo in comments. Addresses merov's comments on the review board. *** Added Merov's compile fixes for windows. --- indra/llmessage/llares.cpp | 17 ++----- indra/llmessage/llcurl.cpp | 2 +- indra/llmessage/lliohttpserver.cpp | 10 ++-- indra/llmessage/lliohttpserver.h | 2 +- indra/llmessage/lliosocket.cpp | 99 ++++++++++++++------------------------ indra/llmessage/lliosocket.h | 33 ++++--------- indra/llmessage/llmail.cpp | 17 ++++--- indra/llmessage/llmail.h | 4 +- indra/llmessage/llpumpio.cpp | 74 ++++++++++------------------ indra/llmessage/llpumpio.h | 31 ++++-------- indra/llmessage/llurlrequest.cpp | 25 ++++++---- indra/llmessage/message.cpp | 17 +++---- indra/llmessage/tests/networkio.h | 9 +--- 13 files changed, 122 insertions(+), 218 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 5a67035ed1..fab9858b69 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llares.h" +#include "llscopedvolatileaprpool.h" #include #include @@ -464,11 +465,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; @@ -482,10 +478,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++) { @@ -502,7 +495,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); @@ -511,7 +504,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]; @@ -520,7 +513,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 a485fa0160..4d3b382f7a 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1039,7 +1039,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 5c1b0531ff..2294e4b8ae 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -50,7 +50,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 ca84fa8bb8..e802d9b3a6 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -35,6 +35,7 @@ #include "llhost.h" #include "llmemtype.h" #include "llpumpio.h" +#include "llthread.h" // // constants @@ -98,51 +99,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; @@ -152,7 +133,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(); @@ -160,8 +141,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(); @@ -175,7 +156,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)) { @@ -196,21 +177,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; @@ -223,7 +211,7 @@ bool LLSocket::blockingConnect(const LLHost& host) APR_UNSPEC, host.getPort(), 0, - mPool))) + mPool()))) { return false; } @@ -234,13 +222,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() @@ -252,10 +238,6 @@ LLSocket::~LLSocket() ll_debug_socket("Destroying socket", mSocket); apr_socket_close(mSocket); } - if(mPool) - { - apr_pool_destroy(mPool); - } } void LLSocket::setOptions() @@ -516,10 +498,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), @@ -579,21 +559,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); @@ -608,7 +582,6 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( { chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket))); pump->addChain(chain, mResponseTimeout); - status = STATUS_OK; } else { @@ -617,7 +590,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; @@ -630,11 +604,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 6806e5084a..1e35225512 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -38,7 +38,6 @@ */ #include "lliopipe.h" -#include "apr_pools.h" #include "apr_network_io.h" #include "llchainio.h" @@ -88,34 +87,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. @@ -150,7 +137,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. @@ -167,8 +154,8 @@ protected: // The apr socket. apr_socket_t* mSocket; - // our memory pool - apr_pool_t* mPool; + // Our memory pool. + LLAPRPool mPool; // The port if we know it. U16 mPort; @@ -293,7 +280,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(); /** @@ -325,7 +312,6 @@ protected: //@} protected: - apr_pool_t* mPool; socket_t mListenSocket; factory_t mReactor; bool mInitialized; @@ -359,8 +345,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 08b31e9c7a..8a898ab1b0 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -50,6 +50,7 @@ #include "llstring.h" #include "lluuid.h" #include "net.h" +#include "llaprpool.h" // // constants @@ -57,7 +58,7 @@ const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096; static bool gMailEnabled = true; -static apr_pool_t* gMailPool; +static LLAPRPool gMailPool; static apr_sockaddr_t* gSockAddr; static apr_socket_t* gMailSocket; @@ -82,7 +83,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)) @@ -139,19 +140,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. @@ -161,7 +162,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 3791714363..0a5c532088 100644 --- a/indra/llmessage/llmail.h +++ b/indra/llmessage/llmail.h @@ -27,15 +27,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 a8d2a0a224..89cfd66e1b 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -37,6 +37,7 @@ #include "llmemtype.h" #include "llstl.h" #include "llstat.h" +#include "llthread.h" // These should not be enabled in production, but they can be // intensely useful during development for finding certain kinds of @@ -162,14 +163,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), @@ -178,21 +177,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) @@ -352,8 +354,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); @@ -825,39 +826,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); -#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); + apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); + apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); #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() @@ -885,21 +862,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(); @@ -1157,7 +1132,8 @@ bool LLPumpIO::handleChainError( LLPumpIO::LLChainInfo::LLChainInfo() : mInit(false), mLock(0), - mEOS(false) + mEOS(false), + mDescriptorsPool(new LLAPRPool(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 9303c9d7fc..75c35ae7ab 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -30,11 +30,12 @@ #define LL_LLPUMPIO_H #include +#include #if LL_LINUX // needed for PATH_MAX in APR. #include #endif -#include "apr_pools.h" +#include "llaprpool.h" #include "llbuffer.h" #include "llframetimer.h" #include "lliopipe.h" @@ -58,9 +59,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 @@ -79,24 +79,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. */ @@ -368,6 +357,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 @@ -386,9 +376,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. + LLAPRPool mPool; + LLAPRPool mCurrentPool; S32 mCurrentPoolReallocCount; #if LL_THREADS_APR @@ -400,8 +390,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/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index cb9d1c3731..83b6f7cf71 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -40,6 +40,7 @@ #include "llstring.h" #include "apr_env.h" #include "llapr.h" +#include "llscopedvolatileaprpool.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -210,27 +211,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 2f0d815be5..302cfc7ca2 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -97,8 +97,10 @@ std::string get_shared_secret(); class LLMessagePollInfo { public: + LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { } apr_socket_t *mAPRSocketp; apr_pollfd_t mPollFD; + LLAPRPool mPool; }; namespace @@ -287,20 +289,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(); - } + mPollInfop = new LLMessagePollInfo; + apr_socket_t *aprSocketp = NULL; - apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp); + apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool()); - mPollInfop = new LLMessagePollInfo; 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/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 2aff90ca1e..23e1c791f4 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -30,7 +30,6 @@ #define LL_NETWORKIO_H #include "llmemory.h" // LLSingleton -#include "llapr.h" #include "llares.h" #include "llpumpio.h" #include "llhttpclient.h" @@ -48,14 +47,8 @@ public: mServicePump(NULL), mDone(false) { - ll_init_apr(); - if (! gAPRPoolp) - { - throw std::runtime_error("Can't initialize APR"); - } - // Create IO Pump to use for HTTP Requests. - mServicePump = new LLPumpIO(gAPRPoolp); + mServicePump = new LLPumpIO; LLHTTPClient::setPump(*mServicePump); if (ll_init_ares() == NULL || !gAres->isInitialized()) { -- cgit v1.2.3 From 1213e5d3548a111a39b6556c6178fc4bc655d367 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Mon, 4 Apr 2011 14:40:32 -0600 Subject: fix a crash inherited from viewer-development --- indra/llmessage/llavatarnamecache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 767001b633..f6a1aca71b 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -561,7 +561,7 @@ void LLAvatarNameCache::eraseUnrefreshed() const LLAvatarName& av_name = cur->second; if (av_name.mExpires < max_unrefreshed) { - const LLUUID& agent_id = it->first; + const LLUUID& agent_id = cur->first; LL_DEBUGS("AvNameCache") << agent_id << " user '" << av_name.mUsername << "' " << "expired " << now - av_name.mExpires << " secs ago" -- cgit v1.2.3 From 6ab0bc878952de08d6ea37876031f65416a5a004 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 1 Sep 2011 16:44:04 -0400 Subject: LLProxy start of code review cleanup. --- indra/llmessage/llcurl.cpp | 2 +- indra/llmessage/llproxy.cpp | 14 ++++++++------ indra/llmessage/llproxy.h | 40 ++++++++++++++++++++++++++-------------- 3 files changed, 35 insertions(+), 21 deletions(-) (limited to 'indra/llmessage') 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 // 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 { 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 -- cgit v1.2.3 From a8d49f7cf54151bfe03049417d59462688946ae0 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 6 Sep 2011 16:54:53 -0400 Subject: LLProxy code review fixes. * Removed check_curl_code and check_curl_multi_code from the global namespace. * Added comments documenting which thread the public methods of LLProxy should be called from. * Corrected grammar in LLSingleton.h * Fixed a buffer scope problem in llpacketring.cpp. --- indra/llmessage/llcurl.cpp | 10 ++++ indra/llmessage/llcurl.h | 9 +++- indra/llmessage/llpacketring.cpp | 16 +++++-- indra/llmessage/llpacketring.h | 3 -- indra/llmessage/llproxy.cpp | 98 ++++++++++++++++++---------------------- indra/llmessage/llproxy.h | 76 +++++++++++++++---------------- 6 files changed, 109 insertions(+), 103 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 2d456b8f3f..ee85f3bbd7 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1213,3 +1213,13 @@ void LLCurl::cleanupClass() } const unsigned int LLCurl::MAX_REDIRECTS = 5; + +// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. +void LLCurlFF::check_curl_code(CURLcode code) +{ + check_curl_code(code); +} +void LLCurlFF::check_curl_multi_code(CURLMcode code) +{ + check_curl_multi_code(code); +} diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 5ab4dc35b9..154dc23edc 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -371,7 +371,12 @@ private: bool mResultReturned; }; -void check_curl_code(CURLcode code); -void check_curl_multi_code(CURLMcode code); +// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. +namespace LLCurlFF +{ + void check_curl_code(CURLcode code); + void check_curl_multi_code(CURLMcode code); +} + #endif // LL_LLCURL_H diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 7628984de4..fc6e9c5193 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -228,13 +228,13 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap) if (LLProxy::isSOCKSProxyEnabled()) { U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; - packet_size = receive_packet(socket, reinterpret_cast(buffer)); + packet_size = receive_packet(socket, static_cast(static_cast(buffer))); if (packet_size > SOCKS_HEADER_SIZE) { // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); - proxywrap_t * header = reinterpret_cast(buffer); + proxywrap_t * header = static_cast(static_cast(buffer)); mLastSender.setAddress(header->addr); mLastSender.setPort(ntohs(header->port)); @@ -353,14 +353,20 @@ BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 bu return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); } - proxywrap_t *socks_header = reinterpret_cast(&mProxyWrappedSendBuffer); + char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + + proxywrap_t *socks_header = static_cast(static_cast(&headered_send_buffer)); socks_header->rsv = 0; socks_header->addr = host.getAddress(); socks_header->port = htons(host.getPort()); socks_header->atype = ADDRESS_IPV4; socks_header->frag = 0; - memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); - return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort()); + return send_packet( h_socket, + headered_send_buffer, + buf_size + SOCKS_HEADER_SIZE, + LLProxy::getInstance()->getUDPProxy().getAddress(), + LLProxy::getInstance()->getUDPProxy().getPort()); } diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index 7edcc834db..b214271e78 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -83,9 +83,6 @@ protected: LLHost mLastSender; LLHost mLastReceivingIF; - - U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; - private: BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); }; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 611a40579d..827a66dea6 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_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake +static apr_status_t 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 @@ -52,7 +52,6 @@ LLProxy::LLProxy(): mProxyMutex(0), mUDPProxy(), mTCPProxy(), - mPool(gAPRPoolp), mHTTPProxy(), mProxyType(LLPROXY_SOCKS), mAuthMethodSelected(METHOD_NOAUTH), @@ -64,14 +63,13 @@ LLProxy::LLProxy(): LLProxy::~LLProxy() { stopSOCKSProxy(); - sUDPProxyEnabled = false; - mHTTPProxyEnabled = false; + disableHTTPProxy(); } /** * @brief Open the SOCKS 5 TCP control channel. * - * Perform a SOCKS 5 authentication and UDP association to the proxy server. + * Perform a SOCKS 5 authentication and UDP association with the proxy server. * * @param proxy The SOCKS 5 server to connect to. * @return SOCKS_OK if successful, otherwise a socks error code from llproxy.h. @@ -84,11 +82,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy) socks_auth_request_t socks_auth_request; socks_auth_response_t socks_auth_response; - socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5 - socks_auth_request.num_methods = 1; // Sending 1 method. - socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method. + socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5 + socks_auth_request.num_methods = 1; // Sending 1 method. + socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method. - result = tcp_blocking_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); + result = tcp_blocking_handshake(mProxyControlChannel, + static_cast(static_cast(&socks_auth_request)), + sizeof(socks_auth_request), + static_cast(static_cast(&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; @@ -103,7 +105,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy) return SOCKS_NOT_ACCEPTABLE; } - // SOCKS 5 USERNAME/PASSWORD authentication + /* SOCKS 5 USERNAME/PASSWORD authentication */ if (socks_auth_response.method == METHOD_PASSWORD) { // The server has requested a username/password combination @@ -115,11 +117,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy) password_auth[1] = socks_username.size(); memcpy(&password_auth[2], socks_username.c_str(), socks_username.size()); password_auth[socks_username.size() + 2] = socks_password.size(); - memcpy(&password_auth[socks_username.size()+3], socks_password.c_str(), socks_password.size()); + memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size()); authmethod_password_reply_t password_reply; - result = tcp_blocking_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); + result = tcp_blocking_handshake(mProxyControlChannel, + password_auth, + request_size, + static_cast(static_cast(&password_reply)), + sizeof(password_reply)); delete[] password_auth; if (result != APR_SUCCESS) @@ -151,7 +157,11 @@ 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_blocking_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply)); + result = tcp_blocking_handshake(mProxyControlChannel, + static_cast(static_cast(&connect_request)), + sizeof(connect_request), + static_cast(static_cast(&connect_reply)), + sizeof(connect_reply)); if (result != APR_SUCCESS) { LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; @@ -170,6 +180,8 @@ S32 LLProxy::proxyHandshake(LLHost proxy) mUDPProxy.setAddress(proxy.getAddress()); // The connection was successful. We now have the UDP port to send requests that need forwarding to. LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; + sUDPProxyEnabled = true; + return SOCKS_OK; } @@ -177,7 +189,8 @@ S32 LLProxy::proxyHandshake(LLHost proxy) * @brief Initiates a SOCKS 5 proxy session. * * Performs basic checks on host to verify that it is a valid address. Opens the control channel - * and then negotiates the proxy connection with the server. + * and then negotiates the proxy connection with the server. Closes any existing SOCKS + * connection before proceeding. Also disables an HTTP proxy if it is using SOCKS as the proxy. * * * @param host Socks server to connect to. @@ -185,45 +198,32 @@ S32 LLProxy::proxyHandshake(LLHost proxy) */ S32 LLProxy::startSOCKSProxy(LLHost host) { - S32 status = SOCKS_OK; - if (host.isOk()) { mTCPProxy = host; } else { - status = SOCKS_INVALID_HOST; + return SOCKS_INVALID_HOST; } - if (mProxyControlChannel && status == SOCKS_OK) - { - tcp_close_channel(&mProxyControlChannel); - } + // Close any running SOCKS connection. + stopSOCKSProxy(); - if (status == SOCKS_OK) + mProxyControlChannel = tcp_open_channel(gAPRPoolp, mTCPProxy); + if (!mProxyControlChannel) { - mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); - if (!mProxyControlChannel) - { - status = SOCKS_HOST_CONNECT_FAILED; - } + return SOCKS_HOST_CONNECT_FAILED; } - if (status == SOCKS_OK) - { - status = proxyHandshake(mTCPProxy); - } + S32 status = proxyHandshake(mTCPProxy); - if (status == SOCKS_OK) - { - sUDPProxyEnabled = true; - } - else + if (status != SOCKS_OK) { // Shut down the proxy if any of the above steps failed. stopSOCKSProxy(); } + return status; } @@ -244,7 +244,7 @@ void LLProxy::stopSOCKSProxy() if (LLPROXY_SOCKS == getHTTPProxyType()) { - void disableHTTPProxy(); + disableHTTPProxy(); } if (mProxyControlChannel) @@ -352,16 +352,6 @@ void LLProxy::disableHTTPProxy() mHTTPProxyEnabled = false; } -/** - * @brief Get the HTTP proxy address and port - */ -// -LLHost LLProxy::getHTTPProxy() const -{ - LLMutexLock lock(&mProxyMutex); - return mHTTPProxy; -} - /** * @brief Get the currently selected HTTP proxy type */ @@ -443,21 +433,21 @@ void LLProxy::applyProxySettings(CURL* handle) // Now test again to verify that the proxy wasn't disabled between the first check and the lock. if (mHTTPProxyEnabled) { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); + LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); + LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); if (mProxyType == LLPROXY_SOCKS) { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); + LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); if (mAuthMethodSelected == METHOD_PASSWORD) { std::string auth_string = mSocksUsername + ":" + mSocksPassword; - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); + LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); } } else { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); + LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); } } } @@ -476,7 +466,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_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +static apr_status_t 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; @@ -544,7 +534,7 @@ static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) /** * @brief Close the socket. * - * @param handle_ptr A pointer-to-pointer to avoid increasing the use count. + * @param handle_ptr The handle of the socket being closed. A pointer-to-pointer to avoid increasing the use count. */ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) { diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index f8478bda30..a919370540 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -226,63 +226,68 @@ public: /*########################################################################################### METHODS THAT DO NOT LOCK mProxyMutex! ###########################################################################################*/ + // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only. LLProxy(); - // static check for enabled status for UDP packets + // Static check for enabled status for UDP packets. Call from main thread only. static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } - // check for enabled status for HTTP packets - // mHTTPProxyEnabled is atomic, so no locking is required for thread safety. - bool isHTTPProxyEnabled() const { return mHTTPProxyEnabled; } - - // Get the UDP proxy address and port + // Get the UDP proxy address and port. Call from main thread only. LLHost getUDPProxy() const { return mUDPProxy; } - // 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! + METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! ###########################################################################################*/ + // Destructor, closes open connections. Do not call directly, use cleanupClass(). ~LLProxy(); - // Start a connection to the SOCKS 5 proxy + // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be + // destroyed before the call to apr_terminate. Call from main thread only. + static void cleanupClass(); + + // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. + // Safe to call from any thread. + void applyProxySettings(CURL* handle); + void applyProxySettings(LLCurl::Easy* handle); + void applyProxySettings(LLCurlEasyRequest* handle); + + // Start a connection to the SOCKS 5 proxy. Call from main thread only. S32 startSOCKSProxy(LLHost host); - // Disconnect and clean up any connection to the SOCKS 5 proxy + // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from main thread only. void stopSOCKSProxy(); - // Delete LLProxy singleton, destroying the APR pool used by the control channel. - static void cleanupClass(); - - // Set up to use Password auth when connecting to the SOCKS proxy + // Use Password auth when connecting to the SOCKS proxy. Call from main thread only. bool setAuthPassword(const std::string &username, const std::string &password); - // Set up to use No Auth when connecting to the SOCKS proxy + // Disable authentication when connecting to the SOCKS proxy. Call from main thread only. void setAuthNone(); - // Get the currently selected auth method. - LLSocks5AuthType getSelectedAuthMethod() const; - - // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy - // as specified in type + // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy. + // as specified in type. Call from main thread only. bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type); bool enableHTTPProxy(); - // Stop proxying HTTP packets + // Stop proxying HTTP packets. Call from main thread only. void disableHTTPProxy(); - // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. - void applyProxySettings(CURL* handle); - void applyProxySettings(LLCurl::Easy* handle); - void applyProxySettings(LLCurlEasyRequest* handle); + /*########################################################################################### + END OF LOCKING METHODS + ###########################################################################################*/ +private: + /*########################################################################################### + METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! + ###########################################################################################*/ - // Get the HTTP proxy address and port - LLHost getHTTPProxy() const; + // Perform a SOCKS 5 authentication and UDP association with the proxy server. + S32 proxyHandshake(LLHost proxy); + + // Get the currently selected auth method. + LLSocks5AuthType getSelectedAuthMethod() const; // Get the currently selected HTTP proxy type LLHttpProxyType getHTTPProxyType() const; @@ -293,17 +298,13 @@ public: /*########################################################################################### END OF LOCKING METHODS ###########################################################################################*/ -private: - // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort. - S32 proxyHandshake(LLHost proxy); private: - // Is the HTTP proxy enabled? - // Safe to read in any thread, do not write directly, - // use enableHTTPProxy() and disableHTTPProxy() instead. + // Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly. + // Instead use enableHTTPProxy() and disableHTTPProxy() instead. mutable LLAtomic32 mHTTPProxyEnabled; - // Mutex to protect shared members in non-main thread calls to applyProxySettings() + // Mutex to protect shared members in non-main thread calls to applyProxySettings(). mutable LLMutex mProxyMutex; /*########################################################################################### @@ -321,9 +322,6 @@ private: // socket handle to proxy TCP control channel LLSocket::ptr_t mProxyControlChannel; - // APR pool for the socket - apr_pool_t* mPool; - /*########################################################################################### END OF UNSHARED MEMBERS ###########################################################################################*/ -- cgit v1.2.3 From f73b795bb709b3060e06b4238ae4dac702f21301 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 6 Sep 2011 17:33:18 -0400 Subject: Renamed LLCurl::check_curl_code() and LLCurl::check_curl_multi_code() to prevent ambiguous name build error. --- indra/llmessage/llcurl.cpp | 4 ++-- indra/llmessage/llcurl.h | 5 ++--- indra/llmessage/llproxy.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index ee85f3bbd7..785d07acb8 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1215,11 +1215,11 @@ void LLCurl::cleanupClass() const unsigned int LLCurl::MAX_REDIRECTS = 5; // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. -void LLCurlFF::check_curl_code(CURLcode code) +void LLCurlFF::check_easy_code(CURLcode code) { check_curl_code(code); } -void LLCurlFF::check_curl_multi_code(CURLMcode code) +void LLCurlFF::check_multi_code(CURLMcode code) { check_curl_multi_code(code); } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 154dc23edc..213b281e72 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -374,9 +374,8 @@ private: // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. namespace LLCurlFF { - void check_curl_code(CURLcode code); - void check_curl_multi_code(CURLMcode code); + void check_easy_code(CURLcode code); + void check_multi_code(CURLMcode code); } - #endif // LL_LLCURL_H diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 827a66dea6..b26ac42899 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -433,21 +433,21 @@ void LLProxy::applyProxySettings(CURL* handle) // Now test again to verify that the proxy wasn't disabled between the first check and the lock. if (mHTTPProxyEnabled) { - LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); - LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); if (mProxyType == LLPROXY_SOCKS) { - LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); if (mAuthMethodSelected == METHOD_PASSWORD) { std::string auth_string = mSocksUsername + ":" + mSocksPassword; - LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); } } else { - LLCurlFF::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); + LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); } } } -- cgit v1.2.3 From 7d381c65969678281dba056e77ff8423ccfe186a Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 8 Sep 2011 10:43:07 -0400 Subject: LLProxy: Moved the enabling of the UDP proxy back into startSOCKSProxy() --- indra/llmessage/llproxy.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 3ffe6d2d3b..4a7d326c0e 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -180,7 +180,6 @@ S32 LLProxy::proxyHandshake(LLHost proxy) mUDPProxy.setAddress(proxy.getAddress()); // The connection was successful. We now have the UDP port to send requests that need forwarding to. LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; - sUDPProxyEnabled = true; return SOCKS_OK; } @@ -223,6 +222,11 @@ S32 LLProxy::startSOCKSProxy(LLHost host) // Shut down the proxy if any of the above steps failed. stopSOCKSProxy(); } + else + { + // Connection was successful. + sUDPProxyEnabled = true; + } return status; } -- cgit v1.2.3 From 0a0ae2dd3f3d1f27b5fe13d02118866aa7cbb7d7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 13 Sep 2011 12:45:28 -0500 Subject: STORM-1562 Potential fix for crash in LLCurl::run -- don't run curl_multi_perform from multiple threads simultaneously. --- indra/llmessage/llcurl.cpp | 6 +++++- indra/llmessage/llcurl.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 14e169c6b1..280a8942a8 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -222,7 +222,7 @@ namespace boost std::set LLCurl::Easy::sFreeHandles; std::set LLCurl::Easy::sActiveHandles; LLMutex* LLCurl::Easy::sHandleMutex = NULL; - +LLMutex* LLCurl::Easy::sMultiMutex = NULL; //static CURL* LLCurl::Easy::allocEasyHandle() @@ -606,6 +606,7 @@ void LLCurl::Multi::run() mPerformState = PERFORM_STATE_PERFORMING; if (!mQuitting) { + LLMutexLock lock(LLCurl::Easy::sMultiMutex); doPerform(); } } @@ -1179,6 +1180,7 @@ void LLCurl::initClass(bool multi_threaded) check_curl_code(code); Easy::sHandleMutex = new LLMutex(); + Easy::sMultiMutex = new LLMutex(); #if SAFE_SSL S32 mutex_count = CRYPTO_num_locks(); @@ -1200,6 +1202,8 @@ void LLCurl::cleanupClass() delete Easy::sHandleMutex; Easy::sHandleMutex = NULL; + delete Easy::sMultiMutex; + Easy::sMultiMutex = NULL; for (std::set::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) { diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 213b281e72..a876a1562e 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -251,6 +251,7 @@ private: static std::set sFreeHandles; static std::set sActiveHandles; static LLMutex* sHandleMutex; + static LLMutex* sMultiMutex; }; class LLCurl::Multi : public LLThread -- cgit v1.2.3 From 758b936deaa0e6ea397c49afa5024315415eeb93 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 Sep 2011 13:24:31 -0400 Subject: Trying to fix Mac build issue --- indra/llmessage/llcurl.h | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 indra/llmessage/llcurl.h (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h old mode 100644 new mode 100755 index a876a1562e..87de202717 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -232,6 +232,7 @@ public: private: friend class LLCurl; + friend class LLCurl::Multi; CURL* mCurlEasyHandle; struct curl_slist* mHeaders; -- cgit v1.2.3 From 83732a7083ef50ddbf2c0e1e99aed8fe65c6a63a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 19 Sep 2011 16:39:16 -0500 Subject: SH-2445 Potential fix for crash in LLCurl::Multi::~Multi -- lock sMultiMutex around curl_multi_ calls in LLCurl::Multi destructor --- indra/llmessage/llcurl.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 280a8942a8..6d9213f51b 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -553,6 +553,11 @@ LLCurl::Multi::~Multi() { llassert(isStopped()); + if (LLCurl::sMultiThreaded) + { + LLCurl::Easy::sMultiMutex->lock(); + } + delete mSignal; mSignal = NULL; @@ -573,6 +578,11 @@ LLCurl::Multi::~Multi() check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); --gCurlMultiCount; + + if (LLCurl::sMultiThreaded) + { + LLCurl::Easy::sMultiMutex->unlock(); + } } CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) -- cgit v1.2.3