From c6c65e0a3246d74c8efd48e18f6d975615297e1f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 12:56:37 +0000 Subject: [PATCH 1/2] fix: send periodic watchdog notifications during sleep to prevent timeout The wait_sleep() method sent a single WATCHDOG=1 notification before sleeping for 60-180 minutes. If the total runtime before sleep plus the sleep duration exceeded the 200-minute WatchdogSec, systemd killed the process. Fix by sending WATCHDOG=1 every 60 seconds during the sleep period. https://claude.ai/code/session_01Ps5Qw92ubEyzQQkG3Uvjdk --- .../python3/dist-packages/sdwdate/sdwdate.py | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/usr/lib/python3/dist-packages/sdwdate/sdwdate.py b/usr/lib/python3/dist-packages/sdwdate/sdwdate.py index 8a81876..a323305 100644 --- a/usr/lib/python3/dist-packages/sdwdate/sdwdate.py +++ b/usr/lib/python3/dist-packages/sdwdate/sdwdate.py @@ -858,29 +858,17 @@ def wait_sleep(self): self.unixtime_before_sleep = int(time.time()) - # Using sh sleep in place of - # python's time.sleep(self.sleep_time_seconds). - # The latter uses the system clock for its inactive state time. - # It becomes utterly confused when sclockadj is running. - # - # Reverting back to python's time.sleep. Python's sleep no longer - # seems affected by clock jumps. - # - #sleep_cmd = ("sleep" + - # " " + - # str(self.sleep_time_seconds) + - # "." + - # str(nanoseconds)) - #message = "running command: " + sleep_cmd - #LOGGER.info(message) - # - ## Avoid Popen shell=True. - #sleep_cmd = shlex.split(sleep_cmd) - # - #global sleep_process - #sleep_process = Popen(sleep_cmd) - #sleep_process.wait() - time.sleep(self.sleep_time_seconds + nanoseconds) + ## Send periodic watchdog notifications during sleep to prevent + ## systemd from killing the service due to watchdog timeout. + watchdog_interval_seconds = 60 + total_sleep = self.sleep_time_seconds + nanoseconds + slept = 0 + while slept < total_sleep: + remaining = total_sleep - slept + chunk = min(watchdog_interval_seconds, remaining) + time.sleep(chunk) + slept += chunk + SDNOTIFY_OBJECT.notify("WATCHDOG=1") def check_clock_skew(self): From c1a32789f2655c3e32f4234199165427d638d806 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Apr 2026 08:59:35 +0000 Subject: [PATCH 2/2] fix: convert nanoseconds to seconds in wait_sleep() - root cause of watchdog timeout The actual root cause of the watchdog timeout: nanoseconds from secrets.choice(range(0, 999999999)) was added directly to sleep_time_seconds without dividing by 1e9 first. This resulted in time.sleep() being called with ~500 million seconds (~15 years) instead of ~5640.5 seconds. The process would sleep effectively forever until the systemd watchdog killed it at the 200-minute mark. https://claude.ai/code/session_01Ps5Qw92ubEyzQQkG3Uvjdk --- usr/lib/python3/dist-packages/sdwdate/sdwdate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr/lib/python3/dist-packages/sdwdate/sdwdate.py b/usr/lib/python3/dist-packages/sdwdate/sdwdate.py index a323305..14e6c76 100644 --- a/usr/lib/python3/dist-packages/sdwdate/sdwdate.py +++ b/usr/lib/python3/dist-packages/sdwdate/sdwdate.py @@ -861,7 +861,9 @@ def wait_sleep(self): ## Send periodic watchdog notifications during sleep to prevent ## systemd from killing the service due to watchdog timeout. watchdog_interval_seconds = 60 - total_sleep = self.sleep_time_seconds + nanoseconds + ## nanoseconds is an integer in range [0, 999999999) and must be + ## converted to fractional seconds before adding to sleep duration. + total_sleep = self.sleep_time_seconds + (nanoseconds / 1000000000) slept = 0 while slept < total_sleep: remaining = total_sleep - slept