From f8923abd75a3ffdb19e31d54c6faf9a743a46fc9 Mon Sep 17 00:00:00 2001 From: Alex Burr Date: Tue, 3 Apr 2018 13:58:22 +0100 Subject: [PATCH] Change monitor to using raw clock to avoid premature timeout when the network comes up and sets the wall clock time. --- kano_updater/monitor.py | 7 +++++-- kano_updater/raw_clock.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 kano_updater/raw_clock.py diff --git a/kano_updater/monitor.py b/kano_updater/monitor.py index 0698e399..ef4ed0d9 100644 --- a/kano_updater/monitor.py +++ b/kano_updater/monitor.py @@ -9,6 +9,7 @@ import subprocess from collections import defaultdict import sys +from raw_clock import raw_clock import time import signal import os @@ -103,12 +104,14 @@ def monitor(watchproc, timeout): spoll = SignalPoll(signal.SIGUSR1) - lastEvent = time.time() + raw_clk = raw_clock() + + lastEvent = raw_clk.monotonic_time() pids = MonitorPids(watchpid) while True: - now = time.time() + now = raw_clk.monotonic_time() # check for child events changed = pids.is_changed() if watchproc.poll() is not None: diff --git a/kano_updater/raw_clock.py b/kano_updater/raw_clock.py new file mode 100644 index 00000000..0ae33544 --- /dev/null +++ b/kano_updater/raw_clock.py @@ -0,0 +1,36 @@ +# raw_clock.py +# +# Copyright (C) 2018 Kano Computing Ltd. +# License: http://www.gnu.org/licenses/gpl-2.0.txt GNU GPL v2 +# +# Module to obtain a clock value which is not disturbed by the boot process +# when it obtains time from ntp. +# +# From http://stackoverflow.com/questions/1205722/how-do-i-get-monotonic-time-durations-in-python + + +import ctypes +import os + + +class timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + +class raw_clock: + CLOCK_MONOTONIC_RAW = 4 # see + def __init__(self): + self.librt = ctypes.CDLL('librt.so.1', use_errno=True) + self.clock_gettime = self.librt.clock_gettime + self.clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)] + + + def monotonic_time(self): + t = timespec() + if self.clock_gettime(self.CLOCK_MONOTONIC_RAW, ctypes.pointer(t)) != 0: + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) + return t.tv_sec + t.tv_nsec * 1e-9