Don't use DllMain to call altss destructors
This commit is contained in:
parent
c3b1c31d9b
commit
e5d39a5f4c
22
Alc/ALc.c
22
Alc/ALc.c
@ -786,34 +786,22 @@ static void alc_init(void);
|
||||
static void alc_deinit(void);
|
||||
static void alc_deinit_safe(void);
|
||||
|
||||
UIntMap TlsDestructor;
|
||||
extern UIntMap TlsDestructors;
|
||||
|
||||
#ifndef AL_LIBTYPE_STATIC
|
||||
BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
|
||||
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
// Perform actions based on the reason for calling.
|
||||
switch(ul_reason_for_call)
|
||||
switch(reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
/* Pin the DLL so we won't get unloaded until the process terminates */
|
||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(WCHAR*)hModule, &hModule);
|
||||
InitUIntMap(&TlsDestructor, ~0);
|
||||
InitUIntMap(&TlsDestructors, ~0);
|
||||
alc_init();
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
LockUIntMapRead(&TlsDestructor);
|
||||
for(i = 0;i < TlsDestructor.size;i++)
|
||||
{
|
||||
void *ptr = altss_get(TlsDestructor.array[i].key);
|
||||
altss_dtor_t callback = (altss_dtor_t)TlsDestructor.array[i].value;
|
||||
if(ptr && callback)
|
||||
callback(ptr);
|
||||
}
|
||||
UnlockUIntMapRead(&TlsDestructor);
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
@ -821,7 +809,7 @@ BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserv
|
||||
alc_deinit();
|
||||
else
|
||||
alc_deinit_safe();
|
||||
ResetUIntMap(&TlsDestructor);
|
||||
ResetUIntMap(&TlsDestructors);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -198,6 +198,42 @@ int almtx_timedlock(almtx_t *mtx, const struct timespec *ts)
|
||||
}
|
||||
|
||||
|
||||
/* An associative map of uint:void* pairs. The key is the TLS index (given by
|
||||
* TlsAlloc), and the value is the altss_dtor_t callback. When a thread exits,
|
||||
* it iterates over the thread-local value for each TLS key and calls the
|
||||
* destructor function if they're both not NULL. Placing a PIMAGE_TLS_CALLBACK
|
||||
* function pointer in a ".CRT$XLx" section (where x is a character A to Z)
|
||||
* ensures the CRT will call it similar to DllMain.
|
||||
*/
|
||||
UIntMap TlsDestructors;
|
||||
|
||||
static void NTAPI altss_callback(void* UNUSED(handle), DWORD reason, void* UNUSED(reserved))
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
if(reason != DLL_THREAD_DETACH)
|
||||
return;
|
||||
|
||||
LockUIntMapRead(&TlsDestructors);
|
||||
for(i = 0;i < TlsDestructors.size;i++)
|
||||
{
|
||||
void *ptr = altss_get(TlsDestructors.array[i].key);
|
||||
altss_dtor_t callback = (altss_dtor_t)TlsDestructors.array[i].value;
|
||||
if(ptr && callback)
|
||||
callback(ptr);
|
||||
}
|
||||
UnlockUIntMapRead(&TlsDestructors);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma section(".CRT$XLB",read)
|
||||
__declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK altss_callback_ = altss_callback;
|
||||
#elif defined(__GNUC__)
|
||||
PIMAGE_TLS_CALLBACK altss_callback_ __attribute__((section(".CRT$XLB"))) = altss_callback;
|
||||
#else
|
||||
#warning "No TLS callback support, thread-local contexts may leak references on poorly written applications."
|
||||
PIMAGE_TLS_CALLBACK altss_callback_ = altss_callback;
|
||||
#endif
|
||||
|
||||
int altss_create(altss_t *tss_id, altss_dtor_t callback)
|
||||
{
|
||||
DWORD key = TlsAlloc();
|
||||
@ -206,13 +242,13 @@ int altss_create(altss_t *tss_id, altss_dtor_t callback)
|
||||
|
||||
*tss_id = key;
|
||||
if(callback != NULL)
|
||||
InsertUIntMapEntry(&TlsDestructor, key, callback);
|
||||
InsertUIntMapEntry(&TlsDestructors, key, callback);
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
void altss_delete(altss_t tss_id)
|
||||
{
|
||||
InsertUIntMapEntry(&TlsDestructor, tss_id, NULL);
|
||||
RemoveUIntMapKey(&TlsDestructors, tss_id);
|
||||
TlsFree(tss_id);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ typedef struct UIntMap {
|
||||
ALsizei limit;
|
||||
RWLock lock;
|
||||
} UIntMap;
|
||||
extern UIntMap TlsDestructor;
|
||||
|
||||
void InitUIntMap(UIntMap *map, ALsizei limit);
|
||||
void ResetUIntMap(UIntMap *map);
|
||||
|
Loading…
Reference in New Issue
Block a user