From: senthil.gs@samsung.com Date: Thu, 20 Jun 2019 14:02:45 +0000 (+0530) Subject: Set the queue handle to null before stop & destroy. (#525) X-Git-Tag: accepted/tizen/unified/20190626.040955^0 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fupstream%2Fiotivity.git;a=commitdiff_plain;h=d919583a1e1bd42ade7137140c92ec3db13c9c85 Set the queue handle to null before stop & destroy. (#525) g_sendQueueHandle is set to NULL to prevent new requests from being enqueued. It avoids a race condition which could occur when adding elements to QueueingThread if it's already stopped. Race condition scenario:- Background:- -> If a thread has called CAQueueingThreadStop(), it signals the condition variable to wake up the CAQueueingThreadBaseRoutine. -> After signaling, it waits on the same condition variable to wait for the completion of CAQueueingThreadBaseRoutine. -> CAQueueingThreadBaseRoutine will finish its current task and signals the condition variable. -> CAQueueingThreadStop should wake up upon signal and return back to caller. Issue:- -> CAQueueingThreadAddData also signals the condition variable which can wake up the thread that called CAQueueingThreadStop. -> CAQueueingThreadStop returns back to caller assuming that the CAQueueingThreadBaseRoutine has stopped. But it could still be running. https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/525 (cherry picked from eb98e19b49ab4d4475449f99f3a4a53607dbea01) Change-Id: I5b22c034b30b00fc1ae7f08c37c278c29910345c Signed-off-by: Senthil Kumar G S Signed-off-by: DoHyun Pyun --- diff --git a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c index 0e33b46..ea55c74 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c +++ b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c @@ -111,7 +111,7 @@ static void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data, static CAResult_t CATCPInitializeQueueHandles(); -static void CATCPDeinitializeQueueHandles(); +static void CATCPDeinitializeQueueHandles(CAQueueingThread_t *queueHandle); static void CATCPSendDataThread(void *threadData); @@ -152,11 +152,10 @@ CAResult_t CATCPInitializeQueueHandles() return CA_STATUS_OK; } -void CATCPDeinitializeQueueHandles() +void CATCPDeinitializeQueueHandles(CAQueueingThread_t *queueHandle) { - CAQueueingThreadDestroy(g_sendQueueHandle); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; + CAQueueingThreadDestroy(queueHandle); + OICFree(queueHandle); } void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status) @@ -665,11 +664,18 @@ CAResult_t CAStopTCP() #ifndef SINGLE_THREAD // Stop send queue thread. - if (g_sendQueueHandle && g_sendQueueHandle->threadMutex) + if (g_sendQueueHandle != NULL) { - CAQueueingThreadStop(g_sendQueueHandle); + // g_sendQueueHandle is set to NULL to prevent new requests from being enqueued. + CAQueueingThread_t *queueHandle = g_sendQueueHandle; + g_sendQueueHandle = NULL; + + if (queueHandle->threadMutex) + { + CAQueueingThreadStop(queueHandle); + } + CATCPDeinitializeQueueHandles(queueHandle); } - CATCPDeinitializeQueueHandles(); #endif // Close TCP servers and established connections.