Merge branch 'fix-gldispatch-thread-state-leak' into 'master'

Fix a memory leak in libGLdispatch

Closes #230

See merge request glvnd/libglvnd!265
This commit is contained in:
Kyle Brenneman 2022-06-07 12:54:32 +00:00
commit 7b892b72e0
1 changed files with 22 additions and 2 deletions

View File

@ -42,6 +42,13 @@
*/
static struct glvnd_list currentDispatchList;
/**
* A linked list of __GLdispatchThreadStatePrivate structs that we've
* allocated. This is used to make sure that we clean up if we get unloaded
* while a thread is still current.
*/
static struct glvnd_list threadStatePrivateList;
/*
* Number of clients using GLdispatch.
*/
@ -64,6 +71,8 @@ typedef struct __GLdispatchThreadStatePrivateRec {
/// The current (high-level) __GLdispatch table
__GLdispatchTable *dispatch;
struct glvnd_list entry;
} __GLdispatchThreadStatePrivate;
/*
@ -178,6 +187,7 @@ void __glDispatchInit(void)
glvnd_list_init(&extProcList);
glvnd_list_init(&currentDispatchList);
glvnd_list_init(&dispatchStubList);
glvnd_list_init(&threadStatePrivateList);
// Register GLdispatch's static entrypoints for rewriting
localDispatchStubId = RegisterStubCallbacks(stub_get_patch_callbacks());
@ -588,8 +598,7 @@ PUBLIC GLboolean __glDispatchMakeCurrent(__GLdispatchThreadState *threadState,
DispatchCurrentRef(dispatch);
numCurrentContexts++;
UnlockDispatch();
glvnd_list_add(&priv->entry, &threadStatePrivateList);
/*
* Update the API state with the new values.
@ -599,6 +608,8 @@ PUBLIC GLboolean __glDispatchMakeCurrent(__GLdispatchThreadState *threadState,
priv->threadState = threadState;
threadState->priv = priv;
UnlockDispatch();
/*
* Set the current state in TLS.
*/
@ -624,6 +635,7 @@ static void LoseCurrentInternal(__GLdispatchThreadState *curThreadState,
DispatchCurrentUnref(curThreadState->priv->dispatch);
}
glvnd_list_del(&curThreadState->priv->entry);
free(curThreadState->priv);
curThreadState->priv = NULL;
}
@ -722,6 +734,14 @@ void __glDispatchFini(void)
clientRefcount--;
if (clientRefcount == 0) {
while (!glvnd_list_is_empty(&threadStatePrivateList))
{
__GLdispatchThreadStatePrivate *priv = glvnd_list_first_entry(&threadStatePrivateList,
__GLdispatchThreadStatePrivate, entry);
glvnd_list_del(&priv->entry);
free(priv);
}
/* This frees the dispatchStubList */
UnregisterAllStubCallbacks();