Browse code

c-rest-engine: Adding patch for preprocess timeout

Change-Id: Ied8d29e150297e2f7d468c1130674bb55c037b50
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/4825
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Kumar Kaushik <kaushikk@vmware.com>

Kumar Kaushik authored on 2018/02/24 09:01:31
Showing 2 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 Name:          c-rest-engine
2 2
 Summary:       minimal http(s) server library
3 3
 Version:       1.2
4
-Release:       1%{?dist}
4
+Release:       2%{?dist}
5 5
 Group:         Applications/System
6 6
 Vendor:        VMware, Inc.
7 7
 License:       Apache 2.0
... ...
@@ -12,6 +12,7 @@ BuildRequires: openssl-devel >= 1.0.1
12 12
 Source0:       %{name}-%{version}.tar.gz
13 13
 Patch0:        c-rest-engine-aarch64.patch
14 14
 Patch1:        c-rest-engine-fix-log-file-len.patch
15
+Patch2:        preprocess-timeout.patch
15 16
 %define sha1   c-rest-engine=25aa9d1f2680e26114dee18365c510692552f8e4
16 17
 
17 18
 %description
... ...
@@ -31,6 +32,7 @@ development libs and header files for c-rest-engine
31 31
 %setup -q
32 32
 %patch0 -p1
33 33
 %patch1 -p1
34
+%patch2 -p1
34 35
 
35 36
 %build
36 37
 cd build
... ...
@@ -64,6 +66,8 @@ find %{buildroot} -name '*.la' -delete
64 64
 # %doc ChangeLog README COPYING
65 65
 
66 66
 %changelog
67
+*  Fri Feb 23 2018 Kumar Kaushik <kaushikk@vmware.com> 1.2-2
68
+-  Appying patch for preprocess timeout.
67 69
 *  Wed Feb 14 2018 Kumar Kaushik <kaushikk@vmware.com> 1.2-1
68 70
 -  Upgrading to version 1.2. Removing all upstream patches.
69 71
 *  Thu Nov 23 2017 Priyesh Padmavilasom <ppadmavilasom@vmware.com> 1.1-1
70 72
new file mode 100644
... ...
@@ -0,0 +1,776 @@
0
+From 7b8f80e2846fabd25f7d8081ecf4e6d01b88db1b Mon Sep 17 00:00:00 2001
1
+From: Kumar Kaushik <kaushikk@vmware.com>
2
+Date: Wed, 21 Feb 2018 15:20:36 -0800
3
+Subject: [PATCH] Preprocess timeouts and avoid any race
4
+
5
+Change-Id: Idf091f71e81256d3b9fa15268b2f7fac8b6de551
6
+---
7
+ common/sockinterface.c               |  30 +--
8
+ server/restengine/httpProtocolHead.c |  38 ++--
9
+ transport/posix/socket.c             | 418 +++++++++++++++++------------------
10
+ transport/posix/structs.h            |   2 +-
11
+ 4 files changed, 230 insertions(+), 258 deletions(-)
12
+
13
+diff --git a/common/sockinterface.c b/common/sockinterface.c
14
+index f737f78..197dd48 100644
15
+--- a/common/sockinterface.c
16
+@@ -431,17 +431,11 @@ VmRESTOnConnectionTimeout(
17
+ 
18
+     VMREST_LOG_DEBUG(pRESTHandle,"%s","Connection Timeout..Closing conn..");
19
+ 
20
+-    dwError = VmRESTSendFailureResponse(
21
+-                  pRESTHandle,
22
+-                  errCodeTimeOut,
23
+-                  pRequest
24
+-                  );
25
+-    if (dwError != REST_ENGINE_SUCCESS)
26
+-    {
27
+-        VMREST_LOG_ERROR(pRESTHandle,"Double Failure case detected with error code %u....", dwError);
28
+-    }
29
+-    dwError = REST_ENGINE_SUCCESS;
30
+-
31
++    VmRESTSendFailureResponse(
32
++        pRESTHandle,
33
++        errCodeTimeOut,
34
++        pRequest
35
++        );
36
+ 
37
+     dwError = VmRESTDisconnectClient(
38
+                      pRESTHandle,
39
+@@ -481,7 +475,6 @@ VmRESTTcpReceiveNewData(
40
+     char*                            pszBuffer = NULL;
41
+     uint32_t                         nProcessed = 0;
42
+     uint32_t                         nBufLen = 0;
43
+-    uint32_t                         ret = REST_ENGINE_SUCCESS;
44
+     BOOLEAN                          bNextIO = FALSE;
45
+ 
46
+     if (!pSocket || !pRESTHandle || !pQueue)
47
+@@ -589,19 +582,6 @@ VmRESTTcpReceiveNewData(
48
+ 
49
+     VMREST_LOG_ERROR(pRESTHandle,"ERROR code %u", dwError);
50
+ 
51
+-    if ((dwError == VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS) && (bNextIO))
52
+-    {
53
+-         ret = VmRESTOnConnectionTimeout(
54
+-                     pRESTHandle,
55
+-                     pSocket
56
+-                     );
57
+-
58
+-         if (ret != REST_ENGINE_SUCCESS)
59
+-         {
60
+-            VMREST_LOG_ERROR(pRESTHandle,"Double failure on deferred timeout processing dwError, = %u", dwError);
61
+-            dwError = REST_ENGINE_ERROR_DOUBLE_FAILURE;
62
+-         }
63
+-    }
64
+     goto cleanup;
65
+ }
66
+ 
67
+diff --git a/server/restengine/httpProtocolHead.c b/server/restengine/httpProtocolHead.c
68
+index a7ca54a..c5b9f3c 100644
69
+--- a/server/restengine/httpProtocolHead.c
70
+@@ -1347,7 +1347,6 @@ VmRESTProcessBuffer(
71
+     )
72
+ {
73
+     uint32_t                         dwError = REST_ENGINE_SUCCESS;
74
+-    uint32_t                         ret = REST_ENGINE_SUCCESS;
75
+     VM_REST_PROCESSING_STATE         prevState = PROCESS_INVALID;
76
+     VM_REST_PROCESSING_STATE         currState = PROCESS_INVALID;
77
+     uint32_t                         nProcessed = 0;
78
+@@ -1415,10 +1414,6 @@ VmRESTProcessBuffer(
79
+                                &(pRequest->pResponse)
80
+                                );
81
+                  VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Application callback returns dwError %u", dwError);
82
+-                 if ((dwError != REST_ENGINE_SUCCESS) && pRequest && pRequest->pResponse && pRequest->pResponse->statusLine)
83
+-                 {
84
+-                     VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Status code: %s, header sent %d", pRequest->pResponse->statusLine->statusCode, pRequest->pResponse->bHeaderSent);
85
+-                 }
86
+                  BAIL_ON_VMREST_ERROR(dwError);
87
+                  bInitiateClose = TRUE;
88
+                  break;
89
+@@ -1446,21 +1441,14 @@ VmRESTProcessBuffer(
90
+ error:
91
+ 
92
+     VMREST_LOG_ERROR(pRESTHandle,"Process buffer failed with error code %u, sending failure response", dwError);
93
+-    ret = VmRESTSendFailureResponse(
94
+-                  pRESTHandle,
95
+-                  dwError,
96
+-                  pRequest
97
+-                  );
98
+-    if (ret != REST_ENGINE_SUCCESS)
99
+-    {
100
+-        VMREST_LOG_ERROR(pRESTHandle,"%s","Double Failure case detected ....");
101
+-        VMREST_LOG_ERROR(pRESTHandle,"%s","possible memory leak");
102
+-        dwError = REST_ENGINE_ERROR_DOUBLE_FAILURE;
103
+-    }
104
+-    else
105
+-    {
106
+-        dwError = REST_ENGINE_SUCCESS;
107
+-    }
108
++    VmRESTSendFailureResponse(
109
++        pRESTHandle,
110
++        dwError,
111
++        pRequest
112
++        );
113
++
114
++    dwError = REST_ENGINE_SUCCESS;
115
++
116
+     goto cleanup;
117
+ 
118
+ }
119
+@@ -1524,13 +1512,19 @@ VmRESTSendFailureResponse(
120
+     uint32_t                         nBytesWritten = 0;
121
+     PVM_REST_HTTP_RESPONSE_PACKET    pResponse = NULL;
122
+ 
123
+-    if (!pRequest || !pRequest->pResponse)
124
++    if (!pRESTHandle || !pRequest || !pRequest->pResponse)
125
+     {
126
+         VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid params");
127
+         dwError =  VMREST_APPLICATION_INVALID_PARAMS;
128
+     }
129
+     BAIL_ON_VMREST_ERROR(dwError);
130
+ 
131
++    if (pRESTHandle->instanceState == VMREST_INSTANCE_STOPPED)
132
++    {
133
++        VMREST_LOG_ERROR(pRESTHandle, "%s", "Library trying to stop .. Rejecting request to send negative response");
134
++        goto cleanup;
135
++    }
136
++
137
+     pResponse = pRequest->pResponse;
138
+ 
139
+     VMREST_LOG_ERROR(pRESTHandle,"Preparing to send negative response to client, Error %u...", errorCode);
140
+@@ -1625,7 +1619,7 @@ VmRESTSendFailureResponse(
141
+     return dwError;
142
+ 
143
+ error:
144
+-    VMREST_LOG_ERROR(pRESTHandle,"%s", "Double failure observed ... No response will be sent to client and connection will be forcefully closed.");
145
++    VMREST_LOG_ERROR(pRESTHandle,"%s", "Double failure observed while sending negative response...");
146
+ 
147
+     goto cleanup;
148
+ 
149
+diff --git a/transport/posix/socket.c b/transport/posix/socket.c
150
+index b34ef15..44cfbfd 100644
151
+--- a/transport/posix/socket.c
152
+@@ -89,6 +89,12 @@ VmRESTCreateSSLObject(
153
+     PVM_SOCKET                       pSocket
154
+     );
155
+ 
156
++static
157
++void
158
++VmSockPosixPreProcessTimeouts(
159
++    PVMREST_HANDLE                   pRESTHandle,
160
++    PVM_SOCK_EVENT_QUEUE             pQueue
161
++    );
162
+ 
163
+ 
164
+ DWORD
165
+@@ -501,9 +507,7 @@ VmSockPosixWaitForEvent(
166
+     BOOLEAN                          bLocked = FALSE;
167
+     VM_SOCK_EVENT_TYPE               eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
168
+     PVM_SOCKET                       pSocket = NULL;
169
+-    BOOLEAN                          bFound = FALSE;
170
+     BOOLEAN                          bFreeEventQueue = 0;
171
+-    int                              i = 0;
172
+ 
173
+     if (!pQueue || !ppSocket || !pEventType)
174
+     {
175
+@@ -550,12 +554,21 @@ VmSockPosixWaitForEvent(
176
+     {
177
+         if (pQueue->iReady < pQueue->nReady)
178
+         {
179
++            /**** Preprocess timeouts ****/
180
++            if (pQueue->iReady == 0)
181
++            {
182
++                VmSockPosixPreProcessTimeouts(
183
++                    pRESTHandle,
184
++                    pQueue
185
++                    ); 
186
++            }
187
++
188
+             struct epoll_event* pEvent = &pQueue->pEventArray[pQueue->iReady];
189
+             PVM_SOCKET pEventSocket = (PVM_SOCKET)pEvent->data.ptr;
190
+ 
191
+             if (!pEventSocket)
192
+             {
193
+-                VMREST_LOG_ERROR(pRESTHandle,"%s","Bad socket information");
194
++                VMREST_LOG_DEBUG(pRESTHandle,"%s","Bad socket information");
195
+                 dwError = ERROR_INVALID_STATE;
196
+                 BAIL_ON_VMREST_ERROR(dwError);
197
+             }
198
+@@ -565,22 +578,16 @@ VmSockPosixWaitForEvent(
199
+             if (pEvent->events & (EPOLLERR | EPOLLHUP))
200
+             {
201
+                 eventType = VM_SOCK_EVENT_TYPE_CONNECTION_CLOSED;
202
+-                dwError = VmSockPosixDeleteEventFromQueue(
203
+-                              pRESTHandle,
204
+-                              pQueue,
205
+-                              pEventSocket
206
+-                              );
207
+-                BAIL_ON_VMREST_ERROR(dwError);
208
+                 pSocket = pEventSocket;
209
++                BAIL_ON_VMREST_ERROR(dwError);
210
+             }
211
+             else if (pEventSocket->type == VM_SOCK_TYPE_LISTENER)    // New connection request
212
+             {
213
+-                VMREST_LOG_INFO(pRESTHandle,"%s","C-REST-ENGINE: ========================  NEW REQUEST ==========================");
214
+                 dwError = VmSockPosixAcceptConnection(
215
+                               pEventSocket,
216
+                               &pSocket);
217
+                 BAIL_ON_VMREST_ERROR(dwError);
218
+-                VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Accepted new connection with socket fd %d", pSocket->fd);
219
++                VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: ( NEW REQUEST ) Accepted new connection with socket fd %d", pSocket->fd);
220
+ 
221
+                 dwError = VmSockPosixSetNonBlocking(pRESTHandle,pSocket);
222
+                 BAIL_ON_VMREST_ERROR(dwError);
223
+@@ -643,120 +650,60 @@ VmSockPosixWaitForEvent(
224
+             }
225
+             else if (pEventSocket->type == VM_SOCK_TYPE_TIMER) // Time out event
226
+             {
227
+-                eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
228
+                 pSocket = pEventSocket;
229
++                VMREST_LOG_INFO(pRESTHandle, "Timeout event happened on IO Socket fd %d, timer fd %d", pSocket->pIoSocket->fd, pSocket->fd);
230
+ 
231
+-                VMREST_LOG_DEBUG(pRESTHandle, "Timeout event happened on timer fd %d", pSocket->fd);
232
+-              
233
+-                if (pSocket->pIoSocket != NULL)
234
++                if (pSocket->pIoSocket)
235
+                 {
236
+-                    /*** Scan pQueue and look for IO event corresponding to this timer event ***/
237
+-                    for ((i = (pQueue->iReady + 1)); i < pQueue->nReady ; i++)
238
+-                    {
239
+-                        struct epoll_event* pEventTemp = &pQueue->pEventArray[i];
240
+-                        PVM_SOCKET pEventSocketTemp = (PVM_SOCKET)pEventTemp->data.ptr;
241
+-                        if (pEventSocketTemp->fd == pEventSocket->pIoSocket->fd)
242
+-                        {
243
+-                            pEventSocket->pIoSocket->pTimerSocket = NULL;
244
+-                            bFound = TRUE;
245
+-                            break;
246
+-                        }
247
+-                    }
248
++                   /**** Delete IO socket from queue so that we don't get any further notification ****/
249
++                    dwError = VmSockPosixDeleteEventFromQueue(
250
++                                  pRESTHandle,
251
++                                  pQueue,
252
++                                  pSocket->pIoSocket
253
++                                  );
254
++                    BAIL_ON_VMREST_ERROR(dwError);
255
+ 
256
+-                    if (bFound)
257
++                    if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->pIoSocket->bSSLHandShakeCompleted)))
258
+                     {
259
+-                        VMREST_LOG_DEBUG(pRESTHandle,"Action: DEFERRED, IO sock found in queue(Succeeding),  Io Sock %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
260
+-                        pEventSocket->pIoSocket->pTimerSocket = NULL;
261
++                        /**** SSL handshake is not completed, no response will be sent, free IoSocket ****/
262
++                        VmSockPosixCloseSocket(pRESTHandle,pSocket->pIoSocket);
263
++                        VmSockPosixReleaseSocket(pRESTHandle,pSocket->pIoSocket);
264
++                        pSocket = NULL;
265
+                     }
266
+                     else
267
+                     {
268
+-                        if (pSocket->pIoSocket->bInUse == TRUE)
269
+-                        {
270
+-                            VMREST_LOG_DEBUG(pRESTHandle,"Action: DEFERRED, IO Soc in use, IoSocket %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
271
+-                            pEventSocket->pIoSocket->pTimerSocket = NULL;
272
+-                        }
273
+-                        else
274
+-                        {
275
+-                             /**** We are good to close actual IO Socket here ****/
276
+-                             VMREST_LOG_INFO(pRESTHandle,"Action: IO DELETION, IoSocket %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
277
+-
278
+-                             pSocket = pEventSocket->pIoSocket;
279
+-                             /**** Delete IO from queue ****/
280
+-                             VmSockPosixDeleteEventFromQueue(
281
+-                                           pRESTHandle,
282
+-                                           pQueue,
283
+-                                           pSocket
284
+-                                           );
285
+-
286
+-                             if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
287
+-                             {
288
+-                                 /**** SSL handshake is not completed, no response will be sent, free IoSocket ****/
289
+-                                 pEventSocket->pIoSocket = NULL;
290
+-                                 VmSockPosixCloseSocket(pRESTHandle,pSocket);
291
+-                                 VmSockPosixReleaseSocket(pRESTHandle,pSocket);
292
+-                                 eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
293
+-                             }
294
+-                             else
295
+-                             {
296
+-                                 eventType = VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT;
297
+-                                 pEventSocket->pIoSocket->pTimerSocket = NULL;
298
+-                             }
299
+-                        }
300
++                        pSocket = pSocket->pIoSocket;
301
++                        eventType = VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT;
302
+                     }
303
+                 }
304
+-
305
+-                /** Close and free the timer socket ****/
306
+-                VmSockPosixCloseSocket(pRESTHandle,pEventSocket);
307
+-                VmSockPosixReleaseSocket(pRESTHandle,pEventSocket);
308
+-
309
+-                if (eventType == VM_SOCK_EVENT_TYPE_UNKNOWN)
310
+-                {
311
+-                    pSocket = NULL;
312
+-                }
313
+             }
314
+             else  // Data available on IO Socket
315
+             {
316
+                  pSocket = pEventSocket;
317
++                 VMREST_LOG_DEBUG(pRESTHandle,"Data notification on socket fd %d", pSocket->fd);
318
++
319
++                 /**** stop the timer ****/
320
++                 dwError = VmSockPosixReArmTimer(
321
++                               pRESTHandle,
322
++                               pSocket->pTimerSocket,
323
++                               0
324
++                               );
325
++                 BAIL_ON_VMREST_ERROR(dwError);
326
+ 
327
+-                 /**** Mark IO socket in use - timer out event cannot modify IO till this is done ****/
328
+-                 pSocket->bInUse = TRUE;
329
+-
330
+-                 if (pSocket->pTimerSocket == NULL)
331
++                 /**** If SSL handshake is not yet complete, do the needful ****/
332
++                 if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
333
+                  {
334
+-                     /**** Time out already occurred on this socket.. request won't be processed ****/
335
+-                     VmSockPosixCloseSocket(pRESTHandle,pSocket);
336
+-                     VmSockPosixReleaseSocket(pRESTHandle,pSocket);
337
++                      dwError = VmRESTAcceptSSLContext(
338
++                                    pRESTHandle,
339
++                                    pSocket,
340
++                                    TRUE
341
++                                    );
342
++                      BAIL_ON_VMREST_ERROR(dwError); 
343
++                      pSocket = NULL;
344
+                  }
345
+                  else
346
+                  {
347
+-                      /**** Process data  ****/
348
+-                      VMREST_LOG_DEBUG(pRESTHandle,"Data notification on socket fd %d", pSocket->fd);
349
+-
350
+-                      /**** If SSL handshake is not yet complete, do the needful ****/
351
+-                      if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
352
+-                      {
353
+-                          dwError = VmRESTAcceptSSLContext(
354
+-                                        pRESTHandle,
355
+-                                        pSocket,
356
+-                                        TRUE
357
+-                                        );
358
+-                          BAIL_ON_VMREST_ERROR(dwError);
359
+-
360
+-                          /**** We do not need IO any more ..mark as available for timer ****/
361
+-                          pSocket->bInUse = FALSE;
362
+-                      }
363
+-                      else
364
+-                      {
365
+-                          eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
366
+-
367
+-                          /*** Disarm timer associated with this IO socket .. dont delete ***/
368
+-                          dwError = VmSockPosixReArmTimer(
369
+-                                        pRESTHandle,
370
+-                                        pSocket->pTimerSocket,
371
+-                                        0
372
+-                                        );
373
+-                          BAIL_ON_VMREST_ERROR(dwError);
374
+-                      }
375
++                      eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
376
+                  }
377
+             }
378
+         }
379
+@@ -792,6 +739,10 @@ VmSockPosixWaitForEvent(
380
+     {
381
+         VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Shutting down...Cleaning worker thread %d", (pQueue->thrCnt  + 1));
382
+     }
383
++    else if(dwError == ERROR_INVALID_STATE)
384
++    {
385
++         VMREST_LOG_DEBUG(pRESTHandle,"%s", "Skipping IO processing for timeout");
386
++    }
387
+     else
388
+     {
389
+         VMREST_LOG_ERROR(pRESTHandle,"Error while processing socket event, dwError = %u", dwError);
390
+@@ -1035,29 +986,11 @@ VmSockPosixRead(
391
+ 
392
+ error:
393
+ 
394
+-    if (pSocket && pRESTHandle && pRESTHandle->pSockContext)
395
++    if (pSocket)
396
+     {
397
+-        /**** Delete the socket from poller ****/
398
+-            VmSockPosixDeleteEventFromQueue(
399
+-            pRESTHandle,
400
+-            pRESTHandle->pSockContext->pEventQueue,
401
+-            pSocket
402
+-            );
403
+-
404
+         pSocket->pszBuffer = NULL;
405
+         pSocket->nProcessed = 0;
406
+         pSocket->nBufData = 0;
407
+-
408
+-        if (pSocket->pTimerSocket)
409
+-        {
410
+-            pSocket->pTimerSocket->pIoSocket = NULL;
411
+-            VmSockPosixReArmTimer(
412
+-                pRESTHandle,
413
+-                pSocket->pTimerSocket,
414
+-                1
415
+-                );
416
+-        }
417
+-
418
+     }
419
+ 
420
+     if (pszBufPrev)
421
+@@ -1197,6 +1130,11 @@ VmSockPosixReleaseSocket(
422
+ {
423
+     if (pSocket)
424
+     {
425
++        if (pSocket->pTimerSocket)
426
++        {
427
++            VmSockPosixFreeSocket(pSocket->pTimerSocket);
428
++            pSocket->pTimerSocket = NULL;
429
++        }
430
+         VmSockPosixFreeSocket(pSocket);
431
+     }
432
+ }
433
+@@ -1210,9 +1148,11 @@ VmSockPosixCloseSocket(
434
+     DWORD                            dwError = REST_ENGINE_SUCCESS;
435
+     int                              ret = 0;
436
+     uint32_t                         errorCode = 0;
437
+-    BOOLEAN                          bLocked = FALSE;
438
++    BOOLEAN                          bLockedIO = FALSE;
439
++    BOOLEAN                          bLockedTimer = FALSE;
440
++    PVM_SOCKET                       pTimerSocket = NULL;
441
+ 
442
+-    if (!pRESTHandle || !pSocket )
443
++    if (!pRESTHandle || !pSocket || !(pRESTHandle->pSockContext))
444
+     {
445
+         VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid Params..");
446
+         dwError = ERROR_INVALID_PARAMETER;
447
+@@ -1221,23 +1161,59 @@ VmSockPosixCloseSocket(
448
+ 
449
+     VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Closing socket with fd %d, Socket Type %u ( 2-Io / 5-Timer )", pSocket->fd, pSocket->type);
450
+ 
451
++    pTimerSocket = pSocket->pTimerSocket;
452
++
453
++    /**** Close the timer socket ****/
454
++    if (pTimerSocket)
455
++    {
456
++        dwError = VmRESTLockMutex(pTimerSocket->pMutex);
457
++        BAIL_ON_VMREST_ERROR(dwError);
458
++
459
++        bLockedTimer = TRUE;
460
++
461
++        dwError = VmSockPosixDeleteEventFromQueue(
462
++                      pRESTHandle,
463
++                      pRESTHandle->pSockContext->pEventQueue,
464
++                      pTimerSocket
465
++                      );
466
++        BAIL_ON_VMREST_ERROR(dwError);
467
++
468
++        if (pTimerSocket->fd > 0)
469
++        {
470
++            close(pTimerSocket->fd);
471
++            pTimerSocket->fd = INVALID;
472
++        }
473
++        VmRESTUnlockMutex(pTimerSocket->pMutex);
474
++        bLockedTimer = FALSE;
475
++    }
476
++
477
+     dwError = VmRESTLockMutex(pSocket->pMutex);
478
+     BAIL_ON_VMREST_ERROR(dwError);
479
+ 
480
+-    bLocked = TRUE;
481
++    bLockedIO = TRUE;
482
+ 
483
+-    if (pSocket->pTimerSocket)
484
++    /**** Delete from queue if this is NOT timeout ****/
485
++    if ((pSocket->type == VM_SOCK_TYPE_SERVER) && (!(pSocket->bTimerExpired)))
486
+     {
487
+-        pSocket->pTimerSocket->pIoSocket = NULL;
488
++         dwError = VmSockPosixDeleteEventFromQueue(
489
++                       pRESTHandle,
490
++                       pRESTHandle->pSockContext->pEventQueue,
491
++                       pSocket
492
++                       );
493
++         BAIL_ON_VMREST_ERROR(dwError);
494
+     }
495
+ 
496
++    /**** Close IO socket fd ****/
497
+     if (pRESTHandle->pSSLInfo->isSecure && pSocket->ssl && (pSocket->type != VM_SOCK_TYPE_TIMER))
498
+     {
499
+-        ret =  SSL_shutdown(pSocket->ssl);
500
+-        if (ret < 0)
501
++        if (pSocket->bSSLHandShakeCompleted)
502
+         {
503
+-            errorCode = SSL_get_error(pSocket->ssl, ret);
504
+-            VMREST_LOG_ERROR(pRESTHandle,"Error on SSL_shutdown on socket %d, return value %d, errorCode %u, errno %d", pSocket->fd, ret, errorCode, errno);
505
++            ret =  SSL_shutdown(pSocket->ssl);
506
++            if (ret < 0)
507
++            {
508
++                errorCode = SSL_get_error(pSocket->ssl, ret);
509
++                VMREST_LOG_ERROR(pRESTHandle,"Error on SSL_shutdown on socket %d, return value %d, errorCode %u, errno %d", pSocket->fd, ret, errorCode, errno);
510
++            }
511
+         }
512
+         SSL_free(pSocket->ssl);
513
+         pSocket->ssl = NULL;
514
+@@ -1249,17 +1225,25 @@ VmSockPosixCloseSocket(
515
+         pSocket->fd = -1;
516
+     }
517
+ 
518
+-cleanup:
519
++    VmRESTUnlockMutex(pSocket->pMutex);
520
++    bLockedIO = FALSE;
521
+ 
522
+-    if (bLocked)
523
+-    {
524
+-        VmRESTUnlockMutex(pSocket->pMutex);
525
+-    }
526
++cleanup:
527
+ 
528
+     return dwError;
529
+ 
530
+ error:
531
+ 
532
++    if (bLockedTimer)
533
++    {
534
++        VmRESTUnlockMutex(pTimerSocket->pMutex);
535
++    }
536
++
537
++    if (bLockedIO)
538
++    {
539
++        VmRESTUnlockMutex(pSocket->pMutex);
540
++    }
541
++
542
+     goto cleanup;
543
+ }
544
+ 
545
+@@ -1419,7 +1403,7 @@ VmSockPosixAcceptConnection(
546
+     pSocket->pTimerSocket = NULL;
547
+     pSocket->pIoSocket = NULL;
548
+     pSocket->bSSLHandShakeCompleted = FALSE;
549
+-    pSocket->bInUse = FALSE;
550
++    pSocket->bTimerExpired = FALSE;
551
+ 
552
+     *ppSocket = pSocket;
553
+ 
554
+@@ -1639,58 +1623,24 @@ VmSockPosixSetRequestHandle(
555
+ 
556
+     pSocket->nProcessed = nProcessed;
557
+ 
558
+-    if (bCompleted)
559
++    if (!bCompleted)
560
+     {
561
+-        /**** We are done with request - no need to add back to poller *****/
562
+-        if (pSocket->pTimerSocket != NULL)
563
+-        {
564
+-            pSocket->pTimerSocket->pIoSocket = NULL;
565
+-
566
+-            /**** Give immediate notification to timer for cleanup ****/
567
+-            dwError = VmSockPosixReArmTimer(
568
+-                           pRESTHandle,
569
+-                           pSocket->pTimerSocket,
570
+-                           1
571
+-                           );
572
+-            BAIL_ON_VMREST_ERROR(dwError);
573
+-        }
574
+-
575
+-        /**** Delete actual IO socket from poller ****/
576
+-        dwError = VmSockPosixDeleteEventFromQueue(
577
++        /***** Add back IO socket to poller for next IO cycle and restart timer ****/
578
++        dwError = VmSockPosixReArmTimer(
579
+                       pRESTHandle,
580
+-                      pQueue,
581
+-                      pSocket
582
++                      pSocket->pTimerSocket,
583
++                      ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
584
+                       );
585
+         BAIL_ON_VMREST_ERROR(dwError);
586
+-    }
587
+-    else
588
+-    {
589
+-        /***** Add back IO socket to poller for next IO cycle ****/
590
+-        if (pSocket->pTimerSocket == NULL)
591
+-        {
592
+-            /**** Timeout already happened. Notify HTTP layer to send 408 Req timeout - if possible ****/
593
+-            dwError = VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS;
594
+-        }
595
+-        else
596
+-        {
597
+-            /*** Rearm timer and add IO socket to poller ****/
598
+-            dwError = VmSockPosixReArmTimer(
599
+-                           pRESTHandle,
600
+-                           pSocket->pTimerSocket,
601
+-                           ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
602
+-                           );
603
+-            BAIL_ON_VMREST_ERROR(dwError);
604
+ 
605
+-            event.data.ptr = pSocket;
606
+-            event.events = EPOLLIN;
607
++        event.data.ptr = pSocket;
608
++        event.events = EPOLLIN;
609
+ 
610
+-            event.events = event.events | EPOLLONESHOT;
611
++        event.events = event.events | EPOLLONESHOT;
612
+ 
613
+-            if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
614
+-            {
615
+-                dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
616
+-                BAIL_ON_VMREST_ERROR(dwError);
617
+-            }
618
++        if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
619
++        {
620
++            dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
621
+         }
622
+         BAIL_ON_VMREST_ERROR(dwError);
623
+     }
624
+@@ -1701,10 +1651,6 @@ VmSockPosixSetRequestHandle(
625
+     {
626
+         VmRESTUnlockMutex(pSocket->pMutex);
627
+     }
628
+-    if (!bCompleted && pSocket && (pSocket->pTimerSocket != NULL))
629
+-    {
630
+-        pSocket->bInUse = FALSE;
631
+-    }
632
+ 
633
+     return dwError;
634
+ 
635
+@@ -1871,13 +1817,13 @@ VmSockPosixCreateTimer(
636
+ 
637
+     pTimerSocket->type = VM_SOCK_TYPE_TIMER;
638
+     pTimerSocket->fd = timerFd;
639
+-    pTimerSocket->bInUse = FALSE;
640
+     pTimerSocket->pIoSocket = pSocket;
641
+     pTimerSocket->pRequest = NULL;
642
+     pTimerSocket->pszBuffer = NULL;
643
+     pTimerSocket->nBufData = 0;
644
+     pTimerSocket->nProcessed = 0;
645
+     pTimerSocket->pTimerSocket = NULL;
646
++    pTimerSocket->bTimerExpired = FALSE;
647
+ 
648
+     pSocket->pTimerSocket = pTimerSocket;
649
+ 
650
+@@ -1902,6 +1848,11 @@ VmSockPosixCreateTimer(
651
+ 
652
+ error:
653
+ 
654
++    if (timerFd > 0)
655
++    {
656
++        close(timerFd);
657
++    }
658
++
659
+     if (pTimerSocket)
660
+     {
661
+         VmSockPosixFreeSocket(pTimerSocket);
662
+@@ -1988,26 +1939,6 @@ VmRESTAcceptSSLContext(
663
+ 
664
+ error:
665
+ 
666
+-    if (pRESTHandle && pRESTHandle->pSockContext)
667
+-    {
668
+-        /**** Delete from poller ****/
669
+-        VmSockPosixDeleteEventFromQueue(
670
+-            pRESTHandle,
671
+-            pRESTHandle->pSockContext->pEventQueue,
672
+-            pSocket
673
+-            );
674
+-
675
+-        if (bWatched && pSocket && pSocket->pTimerSocket)
676
+-        {
677
+-            pSocket->pTimerSocket->pIoSocket = NULL;
678
+-            VmSockPosixReArmTimer(
679
+-                pRESTHandle,
680
+-                pSocket->pTimerSocket,
681
+-                1
682
+-                );
683
+-        }
684
+-    }
685
+-
686
+     goto cleanup;
687
+ 
688
+ }
689
+@@ -2067,3 +1998,70 @@ VmRESTCreateSSLObject(
690
+     goto cleanup;
691
+ 
692
+ }
693
++
694
++static
695
++void
696
++VmSockPosixPreProcessTimeouts(
697
++    PVMREST_HANDLE                   pRESTHandle,
698
++    PVM_SOCK_EVENT_QUEUE             pQueue
699
++    )
700
++{
701
++    struct epoll_event*              pQueueEvent = NULL;
702
++    PVM_SOCKET                       pSocket = NULL;
703
++    PVM_SOCKET                       pTimerSocket = NULL;
704
++    PVM_SOCKET                       pIoSocket = NULL;
705
++    int                              index = 0;
706
++    uint32_t                         nTimerEvents = 0;
707
++
708
++    /**** Mark all IO socket from corresponding timer as expired ****/
709
++    for (index = 0; index < pQueue->nReady; index++)
710
++    {
711
++        pQueueEvent = &pQueue->pEventArray[index];
712
++        if (pQueueEvent)
713
++        {
714
++            pSocket =  (PVM_SOCKET)pQueueEvent->data.ptr;
715
++            if (pSocket && (pSocket->type == VM_SOCK_TYPE_TIMER))
716
++            {
717
++                pTimerSocket = pSocket;
718
++                pIoSocket = pTimerSocket->pIoSocket;
719
++                if (pIoSocket)
720
++                {
721
++                    pIoSocket->bTimerExpired = TRUE;
722
++                    nTimerEvents++;
723
++                    VMREST_LOG_DEBUG(pRESTHandle,"Timeout found for IoSocket fd %d, Timer fd %d", pIoSocket->fd, pTimerSocket->fd);
724
++                }
725
++                pTimerSocket = NULL;
726
++                pIoSocket = NULL;
727
++            }
728
++            pSocket = NULL;
729
++        }
730
++        pQueueEvent = NULL;
731
++    }
732
++
733
++    /**** Set QueueEvent->data.ptr to NULL for all expired IO socket if present in the current queue - worker will not process those ****/
734
++    if (nTimerEvents > 0)
735
++    {
736
++        pSocket = NULL;
737
++        pQueueEvent = NULL;
738
++        index = 0;
739
++
740
++        for (index = 0; index < pQueue->nReady; index++)
741
++        {
742
++            pQueueEvent = &pQueue->pEventArray[index];
743
++            if (pQueueEvent)
744
++            {
745
++                pSocket =  (PVM_SOCKET)pQueueEvent->data.ptr;
746
++                if (pSocket && (pSocket->type == VM_SOCK_TYPE_SERVER) && (pSocket->bTimerExpired == TRUE))
747
++                {
748
++                    pQueueEvent->data.ptr = NULL;
749
++                    VMREST_LOG_WARNING(pRESTHandle,"Near race detected for IoSocket fd %d", pSocket->fd);
750
++                }
751
++                pSocket = NULL;
752
++            }
753
++            pQueueEvent = NULL;
754
++        }
755
++    }
756
++
757
++    return;
758
++}
759
++
760
+diff --git a/transport/posix/structs.h b/transport/posix/structs.h
761
+index 369cfcb..82047fe 100644
762
+--- a/transport/posix/structs.h
763
+@@ -20,7 +20,7 @@ typedef struct _VM_SOCKET
764
+     int                              fd;
765
+     SSL*                             ssl;
766
+     BOOLEAN                          bSSLHandShakeCompleted;
767
+-    BOOLEAN                          bInUse;
768
++    BOOLEAN                          bTimerExpired;
769
+     char*                            pszBuffer;
770
+     uint32_t                         nBufData;
771
+     uint32_t                         nProcessed;