[ovs-dev] [PATCH v3] timeval: Use monotonic time in OVS Python timeval library.
Ryan Wilson
wryan at nicira.com
Fri May 30 22:38:51 UTC 2014
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 any applications that poll block based on time, such as
ovs-xapi-sync, 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. This has been
tested on Ubuntu 12.04 and Redhat 6.4.
Bug #1189434
Signed-off-by: Ryan Wilson <wryan at nicira.com>
---
v2: Pre-load librt.so.1 library instead of loading at every function
call. Use only CLOCK_MONOTONIC for consistency with OVS C library.
v3: Edit commit message, remove if-linux check
---
python/ovs/timeval.py | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/python/ovs/timeval.py b/python/ovs/timeval.py
index ba0e54e..f2681ac 100644
--- a/python/ovs/timeval.py
+++ b/python/ovs/timeval.py
@@ -12,13 +12,45 @@
# 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
+
+class timespec(ctypes.Structure):
+ _fields_ = [
+ ('tv_sec', ctypes.c_long),
+ ('tv_nsec', ctypes.c_long),
+ ]
+
+try:
+ librt = ctypes.CDLL(LIBRT)
+ clock_gettime = librt.clock_gettime
+ clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
+except:
+ # Librt shared library could not be loaded
+ librt = None
+
+def monotonic():
+ if not librt:
+ return time.time()
+
+ t = timespec()
+ if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) == 0:
+ return t.tv_sec + t.tv_nsec * 1e-9
+ # Kernel does not support CLOCK_MONOTONIC
+ 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
More information about the dev
mailing list