in src/source/CurlApiCallbacks.c [386:473]
STATUS curlApiCallbacksShutdownActiveRequests(PCurlApiCallbacks pCurlApiCallbacks, STREAM_HANDLE streamHandle, UINT64 timeout, BOOL fromCurlThread,
BOOL killThread)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
PCallbacksProvider pCallbacksProvider = NULL;
BOOL requestsLocked = FALSE, hashTableEmpty = FALSE;
PCurlRequest pCurlRequest;
HashEntry hashEntry[STREAM_MAPPING_HASH_TABLE_BUCKET_LENGTH * STREAM_MAPPING_HASH_TABLE_BUCKET_COUNT];
UINT32 hashEntryCount = ARRAY_SIZE(hashEntry), i;
CHK(pCurlApiCallbacks != NULL && pCurlApiCallbacks->pCallbacksProvider != NULL, STATUS_INVALID_ARG);
pCallbacksProvider = pCurlApiCallbacks->pCallbacksProvider;
// Lock for exclusive operation
pCallbacksProvider->clientCallbacks.lockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->activeRequestsLock);
requestsLocked = TRUE;
CHK_STATUS(hashTableIsEmpty(pCurlApiCallbacks->pActiveRequests, &hashTableEmpty));
if (hashTableEmpty) {
DLOGD("pActiveRequests hashtable is empty");
// Early bailout
CHK(FALSE, retStatus);
}
if (IS_VALID_STREAM_HANDLE(streamHandle)) {
hashEntry[0].key = streamHandle;
retStatus = hashTableGet(pCurlApiCallbacks->pActiveRequests, (UINT64) hashEntry[0].key, &hashEntry[0].value);
CHK(retStatus == STATUS_HASH_KEY_NOT_PRESENT || retStatus == STATUS_SUCCESS, retStatus);
if (retStatus == STATUS_HASH_KEY_NOT_PRESENT) {
CHK(FALSE, STATUS_SUCCESS);
}
hashEntryCount = 1;
} else {
// is stream handle is invalid stream handle then delete all active requests.
CHK_STATUS(hashTableGetAllEntries(pCurlApiCallbacks->pActiveRequests, hashEntry, &hashEntryCount));
}
for (i = 0; i < hashEntryCount; ++i) {
// We have the request
pCurlRequest = (PCurlRequest) hashEntry[i].value;
// if killThread is true and we have attempted to terminate curl and curl thread is still blocked inside
// curl call, then kill the thread.
if (killThread && ATOMIC_LOAD_BOOL(&pCurlRequest->requestInfo.terminating)) {
if (ATOMIC_LOAD_BOOL(&pCurlRequest->blockedInCurl)) {
THREAD_CANCEL(pCurlRequest->threadId);
}
} else if (!fromCurlThread) {
// Set the terminating status on the request
ATOMIC_STORE_BOOL(&pCurlRequest->requestInfo.terminating, TRUE);
if (ATOMIC_LOAD_BOOL(&pCurlRequest->blockedInCurl)) {
// Terminate the curl request in flight
terminateCurlSession(pCurlRequest->pCurlResponse, timeout);
}
}
// if fromCurlThread is true then nothing needs to be done since this function is called right before the
// curl thread terminates.
if (fromCurlThread || (killThread && ATOMIC_LOAD_BOOL(&pCurlRequest->requestInfo.terminating))) {
// if curlApiCallbacksShutdownActiveRequests is being called by curl thread, then free all resources
// and the curl thread will then exit. Otherwise also free when we explicitly kill the thread.
CHK_STATUS(hashTableRemove(pCurlApiCallbacks->pActiveRequests, (UINT64) streamHandle));
// Free the request object
CHK_STATUS(freeCurlRequest(&pCurlRequest));
}
}
// No longer need to hold the lock to the requests
pCallbacksProvider->clientCallbacks.unlockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->activeRequestsLock);
requestsLocked = FALSE;
CleanUp:
CHK_LOG_ERR(retStatus);
// Unlock only if previously locked
if (requestsLocked) {
pCallbacksProvider->clientCallbacks.unlockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->activeRequestsLock);
}
LEAVES();
return retStatus;
}