diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 5d86a6415..6c29e3fd2 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -105,6 +105,7 @@ set(llcommon_HEADER_FILES
CMakeLists.txt
aiframetimer.h
+ airecursive.h
aithreadid.h
aithreadsafe.h
bitpack.h
diff --git a/indra/llcommon/airecursive.h b/indra/llcommon/airecursive.h
new file mode 100644
index 000000000..0b22535a8
--- /dev/null
+++ b/indra/llcommon/airecursive.h
@@ -0,0 +1,58 @@
+/**
+ * @file airecursive.h
+ * @brief Declaration of AIRecursive.
+ *
+ * Copyright (c) 2013, 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.
+ *
+ * 05/01/2013
+ * Initial version, written by Aleric Inglewood @ SL
+ */
+
+#ifndef AI_RECURSIVE
+#define AI_RECURSIVE
+
+// Exception safe class to detect recursive calls.
+//
+// A unique, static bool must be passed (thread local if the function is
+// called by more than one thread).
+//
+// Example usage:
+//
+// void f()
+// {
+// static bool recursive;
+// if (recursive) return;
+// AIRecursive dummy(flag);
+// ...
+// }
+
+class AIRecursive {
+ private:
+ bool& mFlag;
+
+ public:
+ AIRecursive(bool& flag) : mFlag(flag) { mFlag = true; }
+ ~AIRecursive() { mFlag = false; }
+};
+
+#endif // AI_RECURSIVE
diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h
index a9f56afff..eff95d83f 100644
--- a/indra/llcommon/aithreadsafe.h
+++ b/indra/llcommon/aithreadsafe.h
@@ -111,10 +111,10 @@ template struct AIAccess;
template struct AISTAccessConst;
template struct AISTAccess;
+// This helper class is needed because offsetof is only allowed on POD types.
template
-class AIThreadSafeBits
+struct AIThreadSafeBitsPOD
{
-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.
@@ -122,7 +122,11 @@ private:
// 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)];
+};
+template
+class AIThreadSafeBits : private AIThreadSafeBitsPOD
+{
public:
// The wrapped objects are constructed in-place with placement new *outside*
// of this object (by AITHREADSAFE macro(s) or derived classes).
@@ -130,20 +134,20 @@ public:
~AIThreadSafeBits() { ptr()->~T(); }
// Only for use by AITHREADSAFE, see below.
- void* memory() const { return const_cast(&mMemory[0]); }
+ void* memory() const { return const_cast(&AIThreadSafeBitsPOD::mMemory[0]); }
// Cast a T* back to AIThreadSafeBits. This is the inverse of memory().
template
static AIThreadSafeBits* wrapper_cast(T2* ptr)
- { return reinterpret_cast*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); }
+ { return static_cast*>(reinterpret_cast*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBitsPOD, mMemory[0]))); }
template
static AIThreadSafeBits const* wrapper_cast(T2 const* ptr)
- { return reinterpret_cast const*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); }
+ { return static_cast const*>(reinterpret_cast const*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBitsPOD, mMemory[0]))); }
protected:
// Accessors.
- T const* ptr() const { return reinterpret_cast(mMemory); }
- T* ptr() { return reinterpret_cast(mMemory); }
+ T const* ptr() const { return reinterpret_cast(AIThreadSafeBitsPOD::mMemory); }
+ T* ptr() { return reinterpret_cast(AIThreadSafeBitsPOD::mMemory); }
};
/**
diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 278f781ae..36f64bace 100644
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -124,6 +124,25 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
#define llverify(func) do {if (func) {}} while(0)
#endif
+// This can be used for function parameters that are only used by llassert.
+// The ellipsis is needed in case the parameter contains comma's (ie, as part of the type,
+// or trailing comma). The first version can be used as first (or only) parameter of a function,
+// or as parameter in the middle when adding a trailing comma, while the second version can be
+// used as last parameter.
+//
+// Example usage:
+//
+// void foo(ASSERT_ONLY(int x));
+// void foo(x, ASSERT_ONLY(int y,) int z);
+// void foo(x/*,*/ ASSERT_ONLY_COMMA(int y)); // The optional /*,*/ makes it just a bit better readable.
+#ifdef SHOW_ASSERT
+#define ASSERT_ONLY(type_param,...) type_param,##__VA_ARGS__
+#define ASSERT_ONLY_COMMA(type_param,...) , type_param,##__VA_ARGS__
+#else
+#define ASSERT_ONLY(type_param,...)
+#define ASSERT_ONLY_COMMA(type_param,...)
+#endif
+
// handy compile-time assert - enforce those template parameters!
#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */
//XXX: used in two places in llcommon/llskipmap.h
diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp
index 3dc3bd3e2..83fac388b 100644
--- a/indra/llmessage/aicurlthread.cpp
+++ b/indra/llmessage/aicurlthread.cpp
@@ -290,7 +290,7 @@ enum refresh_t {
class CurlSocketInfo
{
public:
- CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
+ CurlSocketInfo(MultiHandle& multi_handle, ASSERT_ONLY(CURL* easy,) curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
~CurlSocketInfo();
void set_action(int action);
@@ -300,7 +300,6 @@ class CurlSocketInfo
private:
MultiHandle& mMultiHandle;
- CURL const* mEasy;
curl_socket_t mSocketFd;
int mAction;
bool mDead;
@@ -669,12 +668,10 @@ class MergeIterator
private:
PollSet* mReadPollSet;
PollSet* mWritePollSet;
- int readIndx;
- int writeIndx;
};
MergeIterator::MergeIterator(PollSet* readPollSet, PollSet* writePollSet) :
- mReadPollSet(readPollSet), mWritePollSet(writePollSet), readIndx(0), writeIndx(0)
+ mReadPollSet(readPollSet), mWritePollSet(writePollSet)
{
mReadPollSet->reset();
mWritePollSet->reset();
@@ -766,8 +763,8 @@ std::ostream& operator<<(std::ostream& os, DebugFdSet const& s)
}
#endif
-CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) :
- mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj)
+CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, ASSERT_ONLY(CURL* easy,) curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) :
+ mMultiHandle(multi_handle), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj)
{
llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy);
mMultiHandle.assign(s, this);
diff --git a/indra/llmessage/aihttpheaders.cpp b/indra/llmessage/aihttpheaders.cpp
index f019e05ac..dc9c7b5bf 100644
--- a/indra/llmessage/aihttpheaders.cpp
+++ b/indra/llmessage/aihttpheaders.cpp
@@ -174,7 +174,7 @@ bool AIHTTPReceivedHeaders::equal(std::string const& key1, std::string const& ke
}
for (std::string::const_iterator i1 = key1.begin(), i2 = key2.begin(); i1 != key1.end(); ++i1, ++i2)
{
- if ((*i1 ^ *i2) & 0xdf != 0)
+ if (((*i1 ^ *i2) & 0xdf) != 0)
{
return false;
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 25370f739..1cbb52dab 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -57,6 +57,7 @@
#include "lltabcontainer.h"
#include "v2math.h"
#include "llfasttimer.h"
+#include "airecursive.h"
const S32 MINIMIZED_WIDTH = 160;
const S32 CLOSE_BOX_FROM_TOP = 1;
@@ -1988,9 +1989,16 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
return new_rect;
}
-
void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
{
+ // Stop recursive call sequence
+ // LLFloaterView::bringToFront calls
+ // LLFloater::setFocus calls
+ // LLFloater::setFrontmost calls this again.
+ static bool recursive;
+ if (recursive) { return; }
+ AIRecursive enter(recursive);
+
// *TODO: make this respect floater's mAutoFocus value, instead of
// using parameter
if (child->getHost())
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e947e1cdc..e78617636 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14660,17 +14660,6 @@ This should be as low as possible, but too low may break functionality
Value
0
- UseFreezeTime
-
UseInventoryLinks