55d6b186 |
From 7b8f80e2846fabd25f7d8081ecf4e6d01b88db1b Mon Sep 17 00:00:00 2001
From: Kumar Kaushik <kaushikk@vmware.com>
Date: Wed, 21 Feb 2018 15:20:36 -0800
Subject: [PATCH] Preprocess timeouts and avoid any race
Change-Id: Idf091f71e81256d3b9fa15268b2f7fac8b6de551
---
common/sockinterface.c | 30 +--
server/restengine/httpProtocolHead.c | 38 ++--
transport/posix/socket.c | 418 +++++++++++++++++------------------
transport/posix/structs.h | 2 +-
4 files changed, 230 insertions(+), 258 deletions(-)
diff --git a/common/sockinterface.c b/common/sockinterface.c
index f737f78..197dd48 100644
--- a/common/sockinterface.c
+++ b/common/sockinterface.c
@@ -431,17 +431,11 @@ VmRESTOnConnectionTimeout(
VMREST_LOG_DEBUG(pRESTHandle,"%s","Connection Timeout..Closing conn..");
- dwError = VmRESTSendFailureResponse(
- pRESTHandle,
- errCodeTimeOut,
- pRequest
- );
- if (dwError != REST_ENGINE_SUCCESS)
- {
- VMREST_LOG_ERROR(pRESTHandle,"Double Failure case detected with error code %u....", dwError);
- }
- dwError = REST_ENGINE_SUCCESS;
-
+ VmRESTSendFailureResponse(
+ pRESTHandle,
+ errCodeTimeOut,
+ pRequest
+ );
dwError = VmRESTDisconnectClient(
pRESTHandle,
@@ -481,7 +475,6 @@ VmRESTTcpReceiveNewData(
char* pszBuffer = NULL;
uint32_t nProcessed = 0;
uint32_t nBufLen = 0;
- uint32_t ret = REST_ENGINE_SUCCESS;
BOOLEAN bNextIO = FALSE;
if (!pSocket || !pRESTHandle || !pQueue)
@@ -589,19 +582,6 @@ VmRESTTcpReceiveNewData(
VMREST_LOG_ERROR(pRESTHandle,"ERROR code %u", dwError);
- if ((dwError == VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS) && (bNextIO))
- {
- ret = VmRESTOnConnectionTimeout(
- pRESTHandle,
- pSocket
- );
-
- if (ret != REST_ENGINE_SUCCESS)
- {
- VMREST_LOG_ERROR(pRESTHandle,"Double failure on deferred timeout processing dwError, = %u", dwError);
- dwError = REST_ENGINE_ERROR_DOUBLE_FAILURE;
- }
- }
goto cleanup;
}
diff --git a/server/restengine/httpProtocolHead.c b/server/restengine/httpProtocolHead.c
index a7ca54a..c5b9f3c 100644
--- a/server/restengine/httpProtocolHead.c
+++ b/server/restengine/httpProtocolHead.c
@@ -1347,7 +1347,6 @@ VmRESTProcessBuffer(
)
{
uint32_t dwError = REST_ENGINE_SUCCESS;
- uint32_t ret = REST_ENGINE_SUCCESS;
VM_REST_PROCESSING_STATE prevState = PROCESS_INVALID;
VM_REST_PROCESSING_STATE currState = PROCESS_INVALID;
uint32_t nProcessed = 0;
@@ -1415,10 +1414,6 @@ VmRESTProcessBuffer(
&(pRequest->pResponse)
);
VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Application callback returns dwError %u", dwError);
- if ((dwError != REST_ENGINE_SUCCESS) && pRequest && pRequest->pResponse && pRequest->pResponse->statusLine)
- {
- VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Status code: %s, header sent %d", pRequest->pResponse->statusLine->statusCode, pRequest->pResponse->bHeaderSent);
- }
BAIL_ON_VMREST_ERROR(dwError);
bInitiateClose = TRUE;
break;
@@ -1446,21 +1441,14 @@ VmRESTProcessBuffer(
error:
VMREST_LOG_ERROR(pRESTHandle,"Process buffer failed with error code %u, sending failure response", dwError);
- ret = VmRESTSendFailureResponse(
- pRESTHandle,
- dwError,
- pRequest
- );
- if (ret != REST_ENGINE_SUCCESS)
- {
- VMREST_LOG_ERROR(pRESTHandle,"%s","Double Failure case detected ....");
- VMREST_LOG_ERROR(pRESTHandle,"%s","possible memory leak");
- dwError = REST_ENGINE_ERROR_DOUBLE_FAILURE;
- }
- else
- {
- dwError = REST_ENGINE_SUCCESS;
- }
+ VmRESTSendFailureResponse(
+ pRESTHandle,
+ dwError,
+ pRequest
+ );
+
+ dwError = REST_ENGINE_SUCCESS;
+
goto cleanup;
}
@@ -1524,13 +1512,19 @@ VmRESTSendFailureResponse(
uint32_t nBytesWritten = 0;
PVM_REST_HTTP_RESPONSE_PACKET pResponse = NULL;
- if (!pRequest || !pRequest->pResponse)
+ if (!pRESTHandle || !pRequest || !pRequest->pResponse)
{
VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid params");
dwError = VMREST_APPLICATION_INVALID_PARAMS;
}
BAIL_ON_VMREST_ERROR(dwError);
+ if (pRESTHandle->instanceState == VMREST_INSTANCE_STOPPED)
+ {
+ VMREST_LOG_ERROR(pRESTHandle, "%s", "Library trying to stop .. Rejecting request to send negative response");
+ goto cleanup;
+ }
+
pResponse = pRequest->pResponse;
VMREST_LOG_ERROR(pRESTHandle,"Preparing to send negative response to client, Error %u...", errorCode);
@@ -1625,7 +1619,7 @@ VmRESTSendFailureResponse(
return dwError;
error:
- VMREST_LOG_ERROR(pRESTHandle,"%s", "Double failure observed ... No response will be sent to client and connection will be forcefully closed.");
+ VMREST_LOG_ERROR(pRESTHandle,"%s", "Double failure observed while sending negative response...");
goto cleanup;
diff --git a/transport/posix/socket.c b/transport/posix/socket.c
index b34ef15..44cfbfd 100644
--- a/transport/posix/socket.c
+++ b/transport/posix/socket.c
@@ -89,6 +89,12 @@ VmRESTCreateSSLObject(
PVM_SOCKET pSocket
);
+static
+void
+VmSockPosixPreProcessTimeouts(
+ PVMREST_HANDLE pRESTHandle,
+ PVM_SOCK_EVENT_QUEUE pQueue
+ );
DWORD
@@ -501,9 +507,7 @@ VmSockPosixWaitForEvent(
BOOLEAN bLocked = FALSE;
VM_SOCK_EVENT_TYPE eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
PVM_SOCKET pSocket = NULL;
- BOOLEAN bFound = FALSE;
BOOLEAN bFreeEventQueue = 0;
- int i = 0;
if (!pQueue || !ppSocket || !pEventType)
{
@@ -550,12 +554,21 @@ VmSockPosixWaitForEvent(
{
if (pQueue->iReady < pQueue->nReady)
{
+ /**** Preprocess timeouts ****/
+ if (pQueue->iReady == 0)
+ {
+ VmSockPosixPreProcessTimeouts(
+ pRESTHandle,
+ pQueue
+ );
+ }
+
struct epoll_event* pEvent = &pQueue->pEventArray[pQueue->iReady];
PVM_SOCKET pEventSocket = (PVM_SOCKET)pEvent->data.ptr;
if (!pEventSocket)
{
- VMREST_LOG_ERROR(pRESTHandle,"%s","Bad socket information");
+ VMREST_LOG_DEBUG(pRESTHandle,"%s","Bad socket information");
dwError = ERROR_INVALID_STATE;
BAIL_ON_VMREST_ERROR(dwError);
}
@@ -565,22 +578,16 @@ VmSockPosixWaitForEvent(
if (pEvent->events & (EPOLLERR | EPOLLHUP))
{
eventType = VM_SOCK_EVENT_TYPE_CONNECTION_CLOSED;
- dwError = VmSockPosixDeleteEventFromQueue(
- pRESTHandle,
- pQueue,
- pEventSocket
- );
- BAIL_ON_VMREST_ERROR(dwError);
pSocket = pEventSocket;
+ BAIL_ON_VMREST_ERROR(dwError);
}
else if (pEventSocket->type == VM_SOCK_TYPE_LISTENER) // New connection request
{
- VMREST_LOG_INFO(pRESTHandle,"%s","C-REST-ENGINE: ======================== NEW REQUEST ==========================");
dwError = VmSockPosixAcceptConnection(
pEventSocket,
&pSocket);
BAIL_ON_VMREST_ERROR(dwError);
- VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Accepted new connection with socket fd %d", pSocket->fd);
+ VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: ( NEW REQUEST ) Accepted new connection with socket fd %d", pSocket->fd);
dwError = VmSockPosixSetNonBlocking(pRESTHandle,pSocket);
BAIL_ON_VMREST_ERROR(dwError);
@@ -643,120 +650,60 @@ VmSockPosixWaitForEvent(
}
else if (pEventSocket->type == VM_SOCK_TYPE_TIMER) // Time out event
{
- eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
pSocket = pEventSocket;
+ VMREST_LOG_INFO(pRESTHandle, "Timeout event happened on IO Socket fd %d, timer fd %d", pSocket->pIoSocket->fd, pSocket->fd);
- VMREST_LOG_DEBUG(pRESTHandle, "Timeout event happened on timer fd %d", pSocket->fd);
-
- if (pSocket->pIoSocket != NULL)
+ if (pSocket->pIoSocket)
{
- /*** Scan pQueue and look for IO event corresponding to this timer event ***/
- for ((i = (pQueue->iReady + 1)); i < pQueue->nReady ; i++)
- {
- struct epoll_event* pEventTemp = &pQueue->pEventArray[i];
- PVM_SOCKET pEventSocketTemp = (PVM_SOCKET)pEventTemp->data.ptr;
- if (pEventSocketTemp->fd == pEventSocket->pIoSocket->fd)
- {
- pEventSocket->pIoSocket->pTimerSocket = NULL;
- bFound = TRUE;
- break;
- }
- }
+ /**** Delete IO socket from queue so that we don't get any further notification ****/
+ dwError = VmSockPosixDeleteEventFromQueue(
+ pRESTHandle,
+ pQueue,
+ pSocket->pIoSocket
+ );
+ BAIL_ON_VMREST_ERROR(dwError);
- if (bFound)
+ if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->pIoSocket->bSSLHandShakeCompleted)))
{
- VMREST_LOG_DEBUG(pRESTHandle,"Action: DEFERRED, IO sock found in queue(Succeeding), Io Sock %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
- pEventSocket->pIoSocket->pTimerSocket = NULL;
+ /**** SSL handshake is not completed, no response will be sent, free IoSocket ****/
+ VmSockPosixCloseSocket(pRESTHandle,pSocket->pIoSocket);
+ VmSockPosixReleaseSocket(pRESTHandle,pSocket->pIoSocket);
+ pSocket = NULL;
}
else
{
- if (pSocket->pIoSocket->bInUse == TRUE)
- {
- VMREST_LOG_DEBUG(pRESTHandle,"Action: DEFERRED, IO Soc in use, IoSocket %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
- pEventSocket->pIoSocket->pTimerSocket = NULL;
- }
- else
- {
- /**** We are good to close actual IO Socket here ****/
- VMREST_LOG_INFO(pRESTHandle,"Action: IO DELETION, IoSocket %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
-
- pSocket = pEventSocket->pIoSocket;
- /**** Delete IO from queue ****/
- VmSockPosixDeleteEventFromQueue(
- pRESTHandle,
- pQueue,
- pSocket
- );
-
- if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
- {
- /**** SSL handshake is not completed, no response will be sent, free IoSocket ****/
- pEventSocket->pIoSocket = NULL;
- VmSockPosixCloseSocket(pRESTHandle,pSocket);
- VmSockPosixReleaseSocket(pRESTHandle,pSocket);
- eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
- }
- else
- {
- eventType = VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT;
- pEventSocket->pIoSocket->pTimerSocket = NULL;
- }
- }
+ pSocket = pSocket->pIoSocket;
+ eventType = VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT;
}
}
-
- /** Close and free the timer socket ****/
- VmSockPosixCloseSocket(pRESTHandle,pEventSocket);
- VmSockPosixReleaseSocket(pRESTHandle,pEventSocket);
-
- if (eventType == VM_SOCK_EVENT_TYPE_UNKNOWN)
- {
- pSocket = NULL;
- }
}
else // Data available on IO Socket
{
pSocket = pEventSocket;
+ VMREST_LOG_DEBUG(pRESTHandle,"Data notification on socket fd %d", pSocket->fd);
+
+ /**** stop the timer ****/
+ dwError = VmSockPosixReArmTimer(
+ pRESTHandle,
+ pSocket->pTimerSocket,
+ 0
+ );
+ BAIL_ON_VMREST_ERROR(dwError);
- /**** Mark IO socket in use - timer out event cannot modify IO till this is done ****/
- pSocket->bInUse = TRUE;
-
- if (pSocket->pTimerSocket == NULL)
+ /**** If SSL handshake is not yet complete, do the needful ****/
+ if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
{
- /**** Time out already occurred on this socket.. request won't be processed ****/
- VmSockPosixCloseSocket(pRESTHandle,pSocket);
- VmSockPosixReleaseSocket(pRESTHandle,pSocket);
+ dwError = VmRESTAcceptSSLContext(
+ pRESTHandle,
+ pSocket,
+ TRUE
+ );
+ BAIL_ON_VMREST_ERROR(dwError);
+ pSocket = NULL;
}
else
{
- /**** Process data ****/
- VMREST_LOG_DEBUG(pRESTHandle,"Data notification on socket fd %d", pSocket->fd);
-
- /**** If SSL handshake is not yet complete, do the needful ****/
- if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
- {
- dwError = VmRESTAcceptSSLContext(
- pRESTHandle,
- pSocket,
- TRUE
- );
- BAIL_ON_VMREST_ERROR(dwError);
-
- /**** We do not need IO any more ..mark as available for timer ****/
- pSocket->bInUse = FALSE;
- }
- else
- {
- eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
-
- /*** Disarm timer associated with this IO socket .. dont delete ***/
- dwError = VmSockPosixReArmTimer(
- pRESTHandle,
- pSocket->pTimerSocket,
- 0
- );
- BAIL_ON_VMREST_ERROR(dwError);
- }
+ eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
}
}
}
@@ -792,6 +739,10 @@ VmSockPosixWaitForEvent(
{
VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Shutting down...Cleaning worker thread %d", (pQueue->thrCnt + 1));
}
+ else if(dwError == ERROR_INVALID_STATE)
+ {
+ VMREST_LOG_DEBUG(pRESTHandle,"%s", "Skipping IO processing for timeout");
+ }
else
{
VMREST_LOG_ERROR(pRESTHandle,"Error while processing socket event, dwError = %u", dwError);
@@ -1035,29 +986,11 @@ VmSockPosixRead(
error:
- if (pSocket && pRESTHandle && pRESTHandle->pSockContext)
+ if (pSocket)
{
- /**** Delete the socket from poller ****/
- VmSockPosixDeleteEventFromQueue(
- pRESTHandle,
- pRESTHandle->pSockContext->pEventQueue,
- pSocket
- );
-
pSocket->pszBuffer = NULL;
pSocket->nProcessed = 0;
pSocket->nBufData = 0;
-
- if (pSocket->pTimerSocket)
- {
- pSocket->pTimerSocket->pIoSocket = NULL;
- VmSockPosixReArmTimer(
- pRESTHandle,
- pSocket->pTimerSocket,
- 1
- );
- }
-
}
if (pszBufPrev)
@@ -1197,6 +1130,11 @@ VmSockPosixReleaseSocket(
{
if (pSocket)
{
+ if (pSocket->pTimerSocket)
+ {
+ VmSockPosixFreeSocket(pSocket->pTimerSocket);
+ pSocket->pTimerSocket = NULL;
+ }
VmSockPosixFreeSocket(pSocket);
}
}
@@ -1210,9 +1148,11 @@ VmSockPosixCloseSocket(
DWORD dwError = REST_ENGINE_SUCCESS;
int ret = 0;
uint32_t errorCode = 0;
- BOOLEAN bLocked = FALSE;
+ BOOLEAN bLockedIO = FALSE;
+ BOOLEAN bLockedTimer = FALSE;
+ PVM_SOCKET pTimerSocket = NULL;
- if (!pRESTHandle || !pSocket )
+ if (!pRESTHandle || !pSocket || !(pRESTHandle->pSockContext))
{
VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid Params..");
dwError = ERROR_INVALID_PARAMETER;
@@ -1221,23 +1161,59 @@ VmSockPosixCloseSocket(
VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Closing socket with fd %d, Socket Type %u ( 2-Io / 5-Timer )", pSocket->fd, pSocket->type);
+ pTimerSocket = pSocket->pTimerSocket;
+
+ /**** Close the timer socket ****/
+ if (pTimerSocket)
+ {
+ dwError = VmRESTLockMutex(pTimerSocket->pMutex);
+ BAIL_ON_VMREST_ERROR(dwError);
+
+ bLockedTimer = TRUE;
+
+ dwError = VmSockPosixDeleteEventFromQueue(
+ pRESTHandle,
+ pRESTHandle->pSockContext->pEventQueue,
+ pTimerSocket
+ );
+ BAIL_ON_VMREST_ERROR(dwError);
+
+ if (pTimerSocket->fd > 0)
+ {
+ close(pTimerSocket->fd);
+ pTimerSocket->fd = INVALID;
+ }
+ VmRESTUnlockMutex(pTimerSocket->pMutex);
+ bLockedTimer = FALSE;
+ }
+
dwError = VmRESTLockMutex(pSocket->pMutex);
BAIL_ON_VMREST_ERROR(dwError);
- bLocked = TRUE;
+ bLockedIO = TRUE;
- if (pSocket->pTimerSocket)
+ /**** Delete from queue if this is NOT timeout ****/
+ if ((pSocket->type == VM_SOCK_TYPE_SERVER) && (!(pSocket->bTimerExpired)))
{
- pSocket->pTimerSocket->pIoSocket = NULL;
+ dwError = VmSockPosixDeleteEventFromQueue(
+ pRESTHandle,
+ pRESTHandle->pSockContext->pEventQueue,
+ pSocket
+ );
+ BAIL_ON_VMREST_ERROR(dwError);
}
+ /**** Close IO socket fd ****/
if (pRESTHandle->pSSLInfo->isSecure && pSocket->ssl && (pSocket->type != VM_SOCK_TYPE_TIMER))
{
- ret = SSL_shutdown(pSocket->ssl);
- if (ret < 0)
+ if (pSocket->bSSLHandShakeCompleted)
{
- errorCode = SSL_get_error(pSocket->ssl, ret);
- VMREST_LOG_ERROR(pRESTHandle,"Error on SSL_shutdown on socket %d, return value %d, errorCode %u, errno %d", pSocket->fd, ret, errorCode, errno);
+ ret = SSL_shutdown(pSocket->ssl);
+ if (ret < 0)
+ {
+ errorCode = SSL_get_error(pSocket->ssl, ret);
+ VMREST_LOG_ERROR(pRESTHandle,"Error on SSL_shutdown on socket %d, return value %d, errorCode %u, errno %d", pSocket->fd, ret, errorCode, errno);
+ }
}
SSL_free(pSocket->ssl);
pSocket->ssl = NULL;
@@ -1249,17 +1225,25 @@ VmSockPosixCloseSocket(
pSocket->fd = -1;
}
-cleanup:
+ VmRESTUnlockMutex(pSocket->pMutex);
+ bLockedIO = FALSE;
- if (bLocked)
- {
- VmRESTUnlockMutex(pSocket->pMutex);
- }
+cleanup:
return dwError;
error:
+ if (bLockedTimer)
+ {
+ VmRESTUnlockMutex(pTimerSocket->pMutex);
+ }
+
+ if (bLockedIO)
+ {
+ VmRESTUnlockMutex(pSocket->pMutex);
+ }
+
goto cleanup;
}
@@ -1419,7 +1403,7 @@ VmSockPosixAcceptConnection(
pSocket->pTimerSocket = NULL;
pSocket->pIoSocket = NULL;
pSocket->bSSLHandShakeCompleted = FALSE;
- pSocket->bInUse = FALSE;
+ pSocket->bTimerExpired = FALSE;
*ppSocket = pSocket;
@@ -1639,58 +1623,24 @@ VmSockPosixSetRequestHandle(
pSocket->nProcessed = nProcessed;
- if (bCompleted)
+ if (!bCompleted)
{
- /**** We are done with request - no need to add back to poller *****/
- if (pSocket->pTimerSocket != NULL)
- {
- pSocket->pTimerSocket->pIoSocket = NULL;
-
- /**** Give immediate notification to timer for cleanup ****/
- dwError = VmSockPosixReArmTimer(
- pRESTHandle,
- pSocket->pTimerSocket,
- 1
- );
- BAIL_ON_VMREST_ERROR(dwError);
- }
-
- /**** Delete actual IO socket from poller ****/
- dwError = VmSockPosixDeleteEventFromQueue(
+ /***** Add back IO socket to poller for next IO cycle and restart timer ****/
+ dwError = VmSockPosixReArmTimer(
pRESTHandle,
- pQueue,
- pSocket
+ pSocket->pTimerSocket,
+ ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
);
BAIL_ON_VMREST_ERROR(dwError);
- }
- else
- {
- /***** Add back IO socket to poller for next IO cycle ****/
- if (pSocket->pTimerSocket == NULL)
- {
- /**** Timeout already happened. Notify HTTP layer to send 408 Req timeout - if possible ****/
- dwError = VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS;
- }
- else
- {
- /*** Rearm timer and add IO socket to poller ****/
- dwError = VmSockPosixReArmTimer(
- pRESTHandle,
- pSocket->pTimerSocket,
- ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
- );
- BAIL_ON_VMREST_ERROR(dwError);
- event.data.ptr = pSocket;
- event.events = EPOLLIN;
+ event.data.ptr = pSocket;
+ event.events = EPOLLIN;
- event.events = event.events | EPOLLONESHOT;
+ event.events = event.events | EPOLLONESHOT;
- if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
- {
- dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
- BAIL_ON_VMREST_ERROR(dwError);
- }
+ if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
+ {
+ dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
}
BAIL_ON_VMREST_ERROR(dwError);
}
@@ -1701,10 +1651,6 @@ VmSockPosixSetRequestHandle(
{
VmRESTUnlockMutex(pSocket->pMutex);
}
- if (!bCompleted && pSocket && (pSocket->pTimerSocket != NULL))
- {
- pSocket->bInUse = FALSE;
- }
return dwError;
@@ -1871,13 +1817,13 @@ VmSockPosixCreateTimer(
pTimerSocket->type = VM_SOCK_TYPE_TIMER;
pTimerSocket->fd = timerFd;
- pTimerSocket->bInUse = FALSE;
pTimerSocket->pIoSocket = pSocket;
pTimerSocket->pRequest = NULL;
pTimerSocket->pszBuffer = NULL;
pTimerSocket->nBufData = 0;
pTimerSocket->nProcessed = 0;
pTimerSocket->pTimerSocket = NULL;
+ pTimerSocket->bTimerExpired = FALSE;
pSocket->pTimerSocket = pTimerSocket;
@@ -1902,6 +1848,11 @@ VmSockPosixCreateTimer(
error:
+ if (timerFd > 0)
+ {
+ close(timerFd);
+ }
+
if (pTimerSocket)
{
VmSockPosixFreeSocket(pTimerSocket);
@@ -1988,26 +1939,6 @@ VmRESTAcceptSSLContext(
error:
- if (pRESTHandle && pRESTHandle->pSockContext)
- {
- /**** Delete from poller ****/
- VmSockPosixDeleteEventFromQueue(
- pRESTHandle,
- pRESTHandle->pSockContext->pEventQueue,
- pSocket
- );
-
- if (bWatched && pSocket && pSocket->pTimerSocket)
- {
- pSocket->pTimerSocket->pIoSocket = NULL;
- VmSockPosixReArmTimer(
- pRESTHandle,
- pSocket->pTimerSocket,
- 1
- );
- }
- }
-
goto cleanup;
}
@@ -2067,3 +1998,70 @@ VmRESTCreateSSLObject(
goto cleanup;
}
+
+static
+void
+VmSockPosixPreProcessTimeouts(
+ PVMREST_HANDLE pRESTHandle,
+ PVM_SOCK_EVENT_QUEUE pQueue
+ )
+{
+ struct epoll_event* pQueueEvent = NULL;
+ PVM_SOCKET pSocket = NULL;
+ PVM_SOCKET pTimerSocket = NULL;
+ PVM_SOCKET pIoSocket = NULL;
+ int index = 0;
+ uint32_t nTimerEvents = 0;
+
+ /**** Mark all IO socket from corresponding timer as expired ****/
+ for (index = 0; index < pQueue->nReady; index++)
+ {
+ pQueueEvent = &pQueue->pEventArray[index];
+ if (pQueueEvent)
+ {
+ pSocket = (PVM_SOCKET)pQueueEvent->data.ptr;
+ if (pSocket && (pSocket->type == VM_SOCK_TYPE_TIMER))
+ {
+ pTimerSocket = pSocket;
+ pIoSocket = pTimerSocket->pIoSocket;
+ if (pIoSocket)
+ {
+ pIoSocket->bTimerExpired = TRUE;
+ nTimerEvents++;
+ VMREST_LOG_DEBUG(pRESTHandle,"Timeout found for IoSocket fd %d, Timer fd %d", pIoSocket->fd, pTimerSocket->fd);
+ }
+ pTimerSocket = NULL;
+ pIoSocket = NULL;
+ }
+ pSocket = NULL;
+ }
+ pQueueEvent = NULL;
+ }
+
+ /**** Set QueueEvent->data.ptr to NULL for all expired IO socket if present in the current queue - worker will not process those ****/
+ if (nTimerEvents > 0)
+ {
+ pSocket = NULL;
+ pQueueEvent = NULL;
+ index = 0;
+
+ for (index = 0; index < pQueue->nReady; index++)
+ {
+ pQueueEvent = &pQueue->pEventArray[index];
+ if (pQueueEvent)
+ {
+ pSocket = (PVM_SOCKET)pQueueEvent->data.ptr;
+ if (pSocket && (pSocket->type == VM_SOCK_TYPE_SERVER) && (pSocket->bTimerExpired == TRUE))
+ {
+ pQueueEvent->data.ptr = NULL;
+ VMREST_LOG_WARNING(pRESTHandle,"Near race detected for IoSocket fd %d", pSocket->fd);
+ }
+ pSocket = NULL;
+ }
+ pQueueEvent = NULL;
+ }
+ }
+
+ return;
+}
+
diff --git a/transport/posix/structs.h b/transport/posix/structs.h
index 369cfcb..82047fe 100644
--- a/transport/posix/structs.h
+++ b/transport/posix/structs.h
@@ -20,7 +20,7 @@ typedef struct _VM_SOCKET
int fd;
SSL* ssl;
BOOLEAN bSSLHandShakeCompleted;
- BOOLEAN bInUse;
+ BOOLEAN bTimerExpired;
char* pszBuffer;
uint32_t nBufData;
uint32_t nProcessed; |