xfreerdp: fix multiple egfx-related memory leaks

This commit is contained in:
Marc-André Moreau 2014-06-20 13:52:13 -04:00
parent cd65a0d6b8
commit 78d3c82798
11 changed files with 170 additions and 26 deletions

View File

@ -475,7 +475,7 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data)
{
int error = 0;
int status = 0;
DVCMAN_CHANNEL* channel;
UINT32 dataSize = Stream_GetRemainingLength(data);
@ -504,16 +504,16 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C
{
Stream_SealLength(channel->dvc_data);
Stream_SetPosition(channel->dvc_data, 0);
error = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data);
status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
}
else
{
error = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
status = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
}
return error;
return status;
}

View File

@ -210,6 +210,8 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s
context->ResetGraphics(context, &pdu);
}
free(pdu.monitorDefArray);
return 1;
}
@ -595,6 +597,8 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream*
context->CacheToSurface(context, &pdu);
}
free(pdu.destPts);
return 1;
}
@ -850,7 +854,11 @@ static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
{
int count;
int index;
ULONG_PTR* pKeys = NULL;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
WLog_Print(gfx->log, WLOG_DEBUG, "Terminated");
@ -859,8 +867,41 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
zgfx_context_free(gfx->zgfx);
count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);
for (index = 0; index < count; index++)
{
RDPGFX_DELETE_SURFACE_PDU pdu;
pdu.surfaceId = ((UINT16) pKeys[index]) - 1;
if (context && context->DeleteSurface)
{
context->DeleteSurface(context, &pdu);
}
}
free(pKeys);
HashTable_Free(gfx->SurfaceTable);
for (index = 0; index < gfx->MaxCacheSlot; index++)
{
if (gfx->CacheSlots[index])
{
RDPGFX_EVICT_CACHE_ENTRY_PDU pdu;
pdu.cacheSlot = (UINT16) index;
if (context && context->EvictCacheEntry)
{
context->EvictCacheEntry(context, &pdu);
}
gfx->CacheSlots[index] = NULL;
}
}
free(gfx);
return 0;

View File

@ -38,11 +38,20 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
xf_register_graphics_pipeline(xfc, (RdpgfxClientContext*) e->pInterface);
xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface);
}
}
void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
xfc->rdpei = NULL;
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface);
}
}

View File

@ -610,7 +610,7 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD
{
xfGfxCacheEntry* cacheEntry;
printf("xf_EvictCacheEntry\n");
//printf("xf_EvictCacheEntry\n");
cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, evictCacheEntry->cacheSlot);
@ -639,7 +639,7 @@ int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WI
return 1;
}
void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx)
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
{
xfc->gfx = gfx;
gfx->custom = (void*) xfc;
@ -662,3 +662,11 @@ void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx)
region16_init(&(xfc->invalidRegion));
}
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
{
region16_uninit(&(xfc->invalidRegion));
gfx->custom = NULL;
xfc->gfx = NULL;
}

View File

@ -48,6 +48,7 @@ typedef struct xf_gfx_cache_entry xfGfxCacheEntry;
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height);
void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx);
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx);
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx);
#endif /* __XF_GRAPHICS_PIPELINE_H */

View File

@ -822,25 +822,33 @@ BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y)
void xf_DestroyWindow(xfContext *xfc, xfWindow *window)
{
if(window == NULL)
if (!window)
return;
if (xfc->window == window)
xfc->window = NULL;
if (window->gc)
XFreeGC(xfc->display, window->gc);
if (window->handle)
{
XUnmapWindow(xfc->display, window->handle);
XDestroyWindow(xfc->display, window->handle);
}
free(window);
if (window->xfwin)
munmap(0, sizeof(*window->xfwin));
if (window->shmid >= 0)
close(window->shmid);
shm_unlink(get_shm_id());
window->xfwin = -1;
window->shmid = -1;
free(window);
}
rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd)

View File

@ -517,11 +517,16 @@ out_free:
void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
{
UINT32 index;
int j;
UINT32 i;
for (index = 0; index < settings->DynamicChannelCount; index++)
for (i = 0; i < settings->DynamicChannelCount; i++)
{
free(settings->DynamicChannelArray[index]);
for (j = 0; j < settings->DynamicChannelArray[i]->argc; j++)
free(settings->DynamicChannelArray[i]->argv[j]);
free(settings->DynamicChannelArray[i]->argv);
free(settings->DynamicChannelArray[i]);
}
free(settings->DynamicChannelArray);

View File

@ -179,6 +179,7 @@ static void* svc_plugin_thread_func(void* arg)
IFCALL(plugin->connect_callback, plugin);
SetEvent(plugin->started);
while (1)
{
if (!MessageQueue_Wait(plugin->MsgPipe->In))
@ -238,7 +239,12 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
MessagePipe_Free(plugin->MsgPipe);
CloseHandle(plugin->thread);
if (plugin->started)
{
CloseHandle(plugin->started);
plugin->started = NULL;
}
plugin->channel_entry_points.pVirtualChannelClose(plugin->OpenHandle);
@ -248,10 +254,10 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
plugin->data_in = NULL;
}
IFCALL(plugin->terminate_callback, plugin);
svc_plugin_remove_open_handle_data(plugin->OpenHandle);
svc_plugin_remove_init_handle_data(plugin->InitHandle);
IFCALL(plugin->terminate_callback, plugin);
}
static VOID VCAPITYPE svc_plugin_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -304,9 +310,18 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints)
}
void svc_plugin_terminate(rdpSvcPlugin* plugin)
{
if (plugin->pool)
{
StreamPool_Free(plugin->pool);
plugin->pool = NULL;
}
if (plugin->started)
{
CloseHandle(plugin->started);
plugin->started = NULL;
}
}
int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out)

View File

@ -326,6 +326,8 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown);
/* Hash Table */
typedef void (*KEY_VALUE_FREE_FN)(void* context, void* key, void* value);
struct _wHashTable
{
BOOL synchronized;
@ -342,6 +344,9 @@ struct _wHashTable
unsigned long (*hashFunction)(void* key);
void (*keyDeallocator)(void* key);
void (*valueDeallocator)(void* value);
void* context;
KEY_VALUE_FREE_FN pfnKeyValueFree;
};
typedef struct _wHashTable wHashTable;
@ -354,6 +359,8 @@ WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key);
WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value);
WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key);
WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value);
WINPR_API void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree);
WINPR_API int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys);
WINPR_API wHashTable* HashTable_New(BOOL synchronized);
WINPR_API void HashTable_Free(wHashTable* table);

View File

@ -368,6 +368,9 @@ void HashTable_Clear(wHashTable* table)
{
nextPair = pair->next;
if (table->pfnKeyValueFree)
table->pfnKeyValueFree(table->context, pair->key, pair->value);
if (table->keyDeallocator)
table->keyDeallocator((void*) pair->key);
@ -389,6 +392,48 @@ void HashTable_Clear(wHashTable* table)
LeaveCriticalSection(&table->lock);
}
/**
* Gets the list of keys as an array
*/
int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
{
int iKey;
int count;
int index;
ULONG_PTR* pKeys;
wKeyValuePair* pair;
wKeyValuePair* nextPair;
if (table->synchronized)
EnterCriticalSection(&table->lock);
iKey = 0;
count = table->numOfElements;
pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR));
for (index = 0; index < table->numOfBuckets; index++)
{
pair = table->bucketArray[index];
while (pair)
{
nextPair = pair->next;
pKeys[iKey++] = (ULONG_PTR) pair->key;
pair = nextPair;
}
}
if (table->synchronized)
LeaveCriticalSection(&table->lock);
*ppKeys = pKeys;
return count;
}
/**
* Determines whether the HashTable contains a specific key.
*/
@ -465,6 +510,12 @@ BOOL HashTable_ContainsValue(wHashTable* table, void* value)
return status;
}
void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree)
{
table->context = context;
table->pfnKeyValueFree = pfnKeyValueFree;
}
/**
* Construction, Destruction
*/

View File

@ -144,8 +144,7 @@ int ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys)
}
}
pKeys = (ULONG_PTR*) malloc(sizeof(ULONG_PTR) * count);
ZeroMemory(pKeys, sizeof(ULONG_PTR) * count);
pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR));
index = 0;