gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r29111 - gnunet/src/util


From: gnunet
Subject: [GNUnet-SVN] r29111 - gnunet/src/util
Date: Sun, 8 Sep 2013 19:37:38 +0200

Author: LRN
Date: 2013-09-08 19:37:37 +0200 (Sun, 08 Sep 2013)
New Revision: 29111

Modified:
   gnunet/src/util/network.c
Log:
Fix timing problems in *_select() on W32

1) If timeout is < 1ms, round it up to 1ms, because WaitForMultipleObjects()
   can't wait for time shorter than 1ms (0ms means "don't wait at all").
2) Read data from the wakeup socket before commanding the select thread to
   start selecting. For some reason the socket would be in signalled state
   by the time winsock's select() runs, even though we emptied it the last
   time. So now we empty it beforehand.
   This should prevent us from returning early in some cases.

Modified: gnunet/src/util/network.c
===================================================================
--- gnunet/src/util/network.c   2013-09-08 17:21:33 UTC (rev 29110)
+++ gnunet/src/util/network.c   2013-09-08 17:37:37 UTC (rev 29111)
@@ -1274,7 +1274,8 @@
 
   int i = 0;
   int retcode = 0;
-  DWORD ms_total = 0;
+  uint64_t mcs_total = 0;
+  DWORD ms_rounded = 0;
 
   int nhandles = 0;
 
@@ -1383,22 +1384,23 @@
 
 #else
 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
-  /* calculate how long we need to wait in milliseconds */
+  /* calculate how long we need to wait in microseconds */
   if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
-    ms_total = INFINITE;
+  {
+    mcs_total = INFINITE;
+    ms_rounded = INFINITE;
+  }
   else
   {
-    ms_total = timeout.rel_value_us / 
GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
-    if (timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us > 
0xFFFFFFFFLL - 1)
-    {
-      GNUNET_break (0);
-      ms_total = 0xFFFFFFFF - 1;
-    }
+    mcs_total = timeout.rel_value_us / 
GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
+    ms_rounded = (DWORD) (mcs_total / 
GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
+    if (mcs_total > 0 && ms_rounded == 0)
+      ms_rounded = 1;
   }
   /* select() may be used as a portable way to sleep */
   if (!(rfds || wfds || efds))
   {
-    Sleep (ms_total);
+    Sleep (ms_rounded);
     return 0;
   }
 
@@ -1413,9 +1415,9 @@
     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
 
-    select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 
0, WSA_FLAG_OVERLAPPED);
+    select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
-    select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, 
NULL, 0, WSA_FLAG_OVERLAPPED);
+    select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
     p = 1;
     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
@@ -1518,7 +1520,7 @@
 
   /* If our select returned something or is a 0-timed request, then also check 
the pipes and get out of here! */
   /* Sadly, it means code duplication :( */
-  if ((selectret > 0) || (ms_total == 0))
+  if ((selectret > 0) || (mcs_total == 0))
   {
     /* Read Pipes */
     if (rfds && read_handles)
@@ -1781,6 +1783,10 @@
       sp.tv = &select_timeout;
     }
     FD_SET (select_wakeup_socket, &aread);
+    do
+    {
+      i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
+    } while (i == 1);
     sp.r = &aread;
     sp.w = &awrite;
     sp.e = &aexcept;
@@ -1798,17 +1804,17 @@
   }
 
   handle_array[nhandles] = NULL;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", 
-       nfds, nhandles, (unsigned long long) ms_total);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
+       nfds, nhandles, mcs_total);
   if (nhandles)
   {
     returncode =
-        WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
-         returncode);
+        WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", 
returncode);
   }
   else if (nfds > 0)
   {
+    GNUNET_break (0); /* This branch shouldn't actually be executed...*/
     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
     returncode = WAIT_TIMEOUT;
   }
@@ -1823,11 +1829,11 @@
     /* Don't wake up select-thread when delay is 0, it should return 
immediately
      * and wake up by itself.
      */
-    if (ms_total != 0)
+    if (mcs_total != 0)
       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d 
%d\n", i, sp.status);
-    if (ms_total != 0)
+    if (mcs_total != 0)
     {
       do
       {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]