core: Fix race when deleting channel manager
This PR fixes a possible crash when the channel manager was freed and there were pending messages in the message queue. The problem was that even though the message queue already received the WMQ_QUIT message, it was still possible to enqueue messages after this point. This resulted in unprocessed messages in the queue when it was deleted. The delete handler then called into channel handlers which where aleady freed/deleted. With this PR adding messages after WMQ_QUIT was posted to the message queue returns an error and all channel messages are now processed before the channels are closed/terminated.
This commit is contained in:
parent
81e79a8bac
commit
b5fa928311
@ -730,6 +730,10 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
|
||||
CHANNEL_OPEN_DATA* pChannelOpenData;
|
||||
CHANNEL_CLIENT_DATA* pChannelClientData;
|
||||
|
||||
MessageQueue_PostQuit(channels->queue, 0);
|
||||
|
||||
freerdp_channels_check_fds(channels, instance);
|
||||
|
||||
/* tell all libraries we are shutting down */
|
||||
for (index = 0; index < channels->clientDataCount; index++)
|
||||
{
|
||||
@ -749,7 +753,6 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
|
||||
}
|
||||
|
||||
channels->clientDataCount = 0;
|
||||
MessageQueue_PostQuit(channels->queue, 0);
|
||||
|
||||
for (index = 0; index < channels->openDataCount; index++)
|
||||
{
|
||||
|
@ -477,6 +477,7 @@ extern "C"
|
||||
int tail;
|
||||
int size;
|
||||
int capacity;
|
||||
BOOL closed;
|
||||
wMessage* array;
|
||||
CRITICAL_SECTION lock;
|
||||
HANDLE event;
|
||||
|
@ -75,6 +75,9 @@ BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
|
||||
|
||||
EnterCriticalSection(&queue->lock);
|
||||
|
||||
if (queue->closed)
|
||||
goto out;
|
||||
|
||||
if (queue->size == queue->capacity)
|
||||
{
|
||||
int old_capacity;
|
||||
@ -110,6 +113,9 @@ BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
|
||||
if (queue->size > 0)
|
||||
SetEvent(queue->event);
|
||||
|
||||
if (message->id == WMQ_QUIT)
|
||||
queue->closed = TRUE;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
LeaveCriticalSection(&queue->lock);
|
||||
|
Loading…
Reference in New Issue
Block a user