SPECS/c-rest-engine/preprocess-timeout.patch
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;