Python's time.time() function uses the system wall clock. However, if NTP resets
the wall clock to be a time in the past, then this causes NVPd threads to poll
block indefinitely since the time is unexpectedly negative.

This patch fixes the issue by using time.monotonic() if Python's version >= 3.3.
Otherwise, the timeval module calls out to the librt C shared library and uses
the clock_gettime function with CLOCK_MONOTONIC_*.

Note this is only enabled on Linux-based platforms.

Bug #1189434
Signed-off-by: Ryan Wilson <wr...@nicira.com>
---
 python/ovs/timeval.py |   39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/python/ovs/timeval.py b/python/ovs/timeval.py
index ba0e54e..fb0b967 100644
--- a/python/ovs/timeval.py
+++ b/python/ovs/timeval.py
@@ -12,13 +12,50 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import ctypes
+import sys
 import time
 
+LIBRT = 'librt.so.1'
+CLOCK_MONOTONIC = 1
+CLOCK_MONOTONIC_RAW = 4
+
+def monotonic_linux():
+    class timespec(ctypes.Structure):
+        _fields_ = [
+            ('tv_sec', ctypes.c_long),
+            ('tv_nsec', ctypes.c_long),
+        ]
+
+    try:
+        librt = ctypes.CDLL(LIBRT)
+    except OSError:
+        # Unable to load librt shared library
+        return time.time()
+    clock_gettime = librt.clock_gettime
+    clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
+
+    t = timespec()
+    for clock_type in [CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC]:
+        if clock_gettime(clock_type, ctypes.pointer(t)) == 0:
+            return t.tv_sec + t.tv_nsec * 1e-9
+    # Kernel does not support CLOCK_MONOTONIC_*
+    return time.time()
+
+def monotonic():
+    if sys.platform.startswith('linux'):
+        return monotonic_linux()
+    else:
+        return time.time()
+
+# Use time.monotonic() if Python version >= 3.3
+if not hasattr(time, 'monotonic'):
+    time.monotonic = monotonic
 
 def msec():
     """Returns the current time, as the amount of time since the epoch, in
     milliseconds, as a float."""
-    return time.time() * 1000.0
+    return time.monotonic() * 1000.0
 
 
 def postfork():
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to