From e562437c88d18d206d079aa0ed07f5be57203a4a Mon Sep 17 00:00:00 2001 From: weidai Date: Fri, 18 Jun 2010 07:06:59 +0000 Subject: 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 --- misc.h | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'misc.h') diff --git a/misc.h b/misc.h index ac1cbda..540c0e8 100644 --- a/misc.h +++ b/misc.h @@ -6,7 +6,6 @@ #include // for memcpy and memmove #ifdef _MSC_VER - #include #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 , int instance=0> class Singleton @@ -121,31 +120,23 @@ private: template const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const { - static simple_ptr s_pObject; - static volatile char s_objectState = 0; + static volatile simple_ptr 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"); -- cgit v1.2.1