Fix crash when using wxThreadSpecificInfo from global object ctor.

When not using compiler TLS support (which is the default now), TLS variable
itself needs to be initialized and user-defined code in the global objects
ctor could be called before this happened, resulting in using uninitialized
CRITICAL_SECTION under Windows and a crash.

Fix this by wrapping global wxThreadSpecificInfo itself in an accessor
function ensuring that it is always initialized before use.

Notice that this required adding wxTLS_TYPE_REF() as wxTLS_TYPE() itself can't
be used for the function return value (__thread or similar can only be used on
the variables).

Closes #16009.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75949 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2014-02-20 15:13:36 +00:00
parent d08b801d2c
commit e518e31acd
2 changed files with 17 additions and 8 deletions

View File

@ -44,6 +44,7 @@
#ifdef wxHAS_COMPILER_TLS
#define wxTLS_TYPE(T) wxTHREAD_SPECIFIC_DECL T
#define wxTLS_TYPE_REF(T) T&
#define wxTLS_PTR(var) (&(var))
#define wxTLS_VALUE(var) (var)
#else // !wxHAS_COMPILER_TLS
@ -135,6 +136,7 @@
};
#define wxTLS_TYPE(T) wxTlsValue<T>
#define wxTLS_TYPE_REF(T) wxTLS_TYPE(T)&
#define wxTLS_PTR(var) ((var).Get())
#define wxTLS_VALUE(var) (*(var))
#endif // wxHAS_COMPILER_TLS/!wxHAS_COMPILER_TLS

View File

@ -48,26 +48,33 @@ inline wxAllThreadInfos& GetAllThreadInfos()
}
// Pointer to the current thread's instance
wxTLS_TYPE(wxThreadSpecificInfo*) g_thisThreadInfo;
inline wxTLS_TYPE_REF(wxThreadSpecificInfo*) GetThisThreadInfo()
{
static wxTLS_TYPE(wxThreadSpecificInfo*) s_thisThreadInfo;
return s_thisThreadInfo;
}
#define wxTHIS_THREAD_INFO wxTLS_VALUE(GetThisThreadInfo())
} // anonymous namespace
wxThreadSpecificInfo& wxThreadSpecificInfo::Get()
{
if ( !wxTLS_VALUE(g_thisThreadInfo) )
if ( !wxTHIS_THREAD_INFO )
{
wxTLS_VALUE(g_thisThreadInfo) = new wxThreadSpecificInfo;
wxTHIS_THREAD_INFO = new wxThreadSpecificInfo;
wxCriticalSectionLocker lock(GetAllThreadInfosCS());
GetAllThreadInfos().push_back(
wxSharedPtr<wxThreadSpecificInfo>(wxTLS_VALUE(g_thisThreadInfo)));
wxSharedPtr<wxThreadSpecificInfo>(wxTHIS_THREAD_INFO));
}
return *wxTLS_VALUE(g_thisThreadInfo);
return *wxTHIS_THREAD_INFO;
}
void wxThreadSpecificInfo::ThreadCleanUp()
{
if ( !wxTLS_VALUE(g_thisThreadInfo) )
if ( !wxTHIS_THREAD_INFO )
return; // nothing to do, not used by this thread at all
// find this thread's instance in GetAllThreadInfos() and destroy it
@ -76,10 +83,10 @@ void wxThreadSpecificInfo::ThreadCleanUp()
i != GetAllThreadInfos().end();
++i )
{
if ( i->get() == wxTLS_VALUE(g_thisThreadInfo) )
if ( i->get() == wxTHIS_THREAD_INFO )
{
GetAllThreadInfos().erase(i);
wxTLS_VALUE(g_thisThreadInfo) = NULL;
wxTHIS_THREAD_INFO = NULL;
break;
}
}