Commit 70e6a300 authored by Kyle Brenneman's avatar Kyle Brenneman
Browse files

Fix a memory leak in libGLdispatch

In __glDispatchMakeCurrent, it allocates a
__GLdispatchThreadStatePrivate struct, which would normally get freed in
__glDispatchLoseCurrent.

However, if the library gets unloaded while another thread still has a
current context, then __glDispatchLoseCurrent never gets called, and so
that memory leaks.

Add the __GLdispatchThreadStatePrivate to a linked list so that it can
free any remaining structs in __glDispatchFini.

Fixes #230.
parent 5024e579
Pipeline #588978 passed with stages
in 1 minute and 44 seconds
......@@ -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();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment