summaryrefslogtreecommitdiff
path: root/misc.h
diff options
context:
space:
mode:
authorweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2010-06-18 07:06:59 +0000
committerweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2010-06-18 07:06:59 +0000
commite562437c88d18d206d079aa0ed07f5be57203a4a (patch)
tree2c3909fc3181e50ef34814d62769b02277bc13a5 /misc.h
parent70a991f0023a3bd23bfd6ffd0b665f1dbed701bf (diff)
downloadcryptopp-e562437c88d18d206d079aa0ed07f5be57203a4a.tar.gz
fix possible race condition in Singleton::Ref()
tolerate double destruction of Singleton and g_nullNameValuePairs fix #include of standard headers git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@488 57ff6487-cd31-0410-9ec3-f628ee90f5f0
Diffstat (limited to 'misc.h')
-rw-r--r--misc.h45
1 files changed, 18 insertions, 27 deletions
diff --git a/misc.h b/misc.h
index ac1cbda..540c0e8 100644
--- a/misc.h
+++ b/misc.h
@@ -6,7 +6,6 @@
#include <string.h> // for memcpy and memmove
#ifdef _MSC_VER
- #include <stdlib.h>
#if _MSC_VER >= 1400
// VC2005 workaround: disable declarations that conflict with winnt.h
#define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1
@@ -101,9 +100,9 @@ struct NewObject
T* operator()() const {return new T;}
};
-/*! This function safely initializes a static object in a multithreaded environment without using locks.
- It may leak memory when two threads try to initialize the static object at the same time
- but this should be acceptable since each static object is only initialized once per session.
+/*! This function safely initializes a static object in a multithreaded environment without using locks (for portability).
+ Note that if two threads call Ref() at the same time, they may get back different references, and one object
+ may end up being memory leaked. This is by design.
*/
template <class T, class F = NewObject<T>, int instance=0>
class Singleton
@@ -121,31 +120,23 @@ private:
template <class T, class F, int instance>
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
{
- static simple_ptr<T> s_pObject;
- static volatile char s_objectState = 0;
+ static volatile simple_ptr<T> s_pObject;
+ T *p = s_pObject.m_p;
-retry:
- switch (s_objectState)
+ if (p)
+ return *p;
+
+ T *newObject = m_objectFactory();
+ p = s_pObject.m_p;
+
+ if (p)
{
- case 0:
- s_objectState = 1;
- try
- {
- s_pObject.m_p = m_objectFactory();
- }
- catch(...)
- {
- s_objectState = 0;
- throw;
- }
- s_objectState = 2;
- break;
- case 1:
- goto retry;
- default:
- break;
+ delete newObject;
+ return *p;
}
- return *s_pObject.m_p;
+
+ s_pObject.m_p = newObject;
+ return *newObject;
}
// ************** misc functions ***************
@@ -555,7 +546,7 @@ static std::string StringNarrow(const wchar_t *str, bool throwOnError = true)
#pragma warning(disable: 4996) // 'wcstombs': This function or variable may be unsafe.
#endif
size_t size = wcstombs(NULL, str, 0);
- if (size == -1)
+ if (size == size_t(0)-1)
{
if (throwOnError)
throw InvalidArgument("StringNarrow: wcstombs() call failed");