i have a python application, that contains functions to be called by interval.
def call_repeatedly(interval, func, *args, **kwargs):
stopped = threading.Event()
lock = threading.Lock() # Lock to protect shared state (stopped)
def loop():
while not stopped.wait(interval):
with lock: # Ensure that no other thread is modifying stopped
func(*args, **kwargs)
threading.Thread(target=loop, daemon=True).start()
return stopped.set
'func' here is the function to be called. I have three of 'func' that will be called - in a 300 seconds, 900 seconds and 3600 seconds interval.
The whole python application runs over months on a raspberry pi4 ubuntu system without any problems. Now, i decided to make my raspberry to a development system, create an intel based server with ubuntu and moved the python application. Now, the 300 seconds 600 seconds interval call works, but the 3600 seconds interval call will not proceeded after the second awaited interval, without any error messages.
I tried another approach with python scheduler:
def call_repeatedly(interval, func, *args, **kwargs):
scheduler = sched.scheduler(time.time, time.sleep)
def loop():
func(*args, **kwargs)
scheduler.enter(interval, 1, loop)
scheduler.enter(interval, 1, loop)
threading.Thread(target=scheduler.run, daemon=True).start()
This runs until midnight, then the 3600 seconds call dying again.
I thought, thats could be the powersave mode in the intel N100 chip, that accidentally stops the threading calls, set intel chip to POLL (no power savings), but without luck. The problem persists. 300 and 600 seconds runs, but the 3600 seconds call dying at some point.
The only thing, that i see is, all three calls coincided at the full hour (3600 seconds). But, why works that on a weaker raspberry pi 4 but not in a intel N100?
i have a python application, that contains functions to be called by interval.
def call_repeatedly(interval, func, *args, **kwargs):
stopped = threading.Event()
lock = threading.Lock() # Lock to protect shared state (stopped)
def loop():
while not stopped.wait(interval):
with lock: # Ensure that no other thread is modifying stopped
func(*args, **kwargs)
threading.Thread(target=loop, daemon=True).start()
return stopped.set
'func' here is the function to be called. I have three of 'func' that will be called - in a 300 seconds, 900 seconds and 3600 seconds interval.
The whole python application runs over months on a raspberry pi4 ubuntu system without any problems. Now, i decided to make my raspberry to a development system, create an intel based server with ubuntu and moved the python application. Now, the 300 seconds 600 seconds interval call works, but the 3600 seconds interval call will not proceeded after the second awaited interval, without any error messages.
I tried another approach with python scheduler:
def call_repeatedly(interval, func, *args, **kwargs):
scheduler = sched.scheduler(time.time, time.sleep)
def loop():
func(*args, **kwargs)
scheduler.enter(interval, 1, loop)
scheduler.enter(interval, 1, loop)
threading.Thread(target=scheduler.run, daemon=True).start()
This runs until midnight, then the 3600 seconds call dying again.
I thought, thats could be the powersave mode in the intel N100 chip, that accidentally stops the threading calls, set intel chip to POLL (no power savings), but without luck. The problem persists. 300 and 600 seconds runs, but the 3600 seconds call dying at some point.
The only thing, that i see is, all three calls coincided at the full hour (3600 seconds). But, why works that on a weaker raspberry pi 4 but not in a intel N100?
Share Improve this question edited Feb 5 at 20:37 toyota Supra 4,5518 gold badges21 silver badges24 bronze badges asked Feb 5 at 10:29 PythonairePythonaire 13 bronze badges 2 |2 Answers
Reset to default 0After many "try and errors" ... it's not the call_repeatedly function itself. The threads created with call_repeatedly trying to access a singleton . Sometimes they can collide. Using threading.Lock() while accessing the singleton helps. The curious fact is, that the collision scenario never happend on the raspberry, but now on the Intel chipset.
Try replacing time.sleep()
Instead of sched.scheduler
to avoid dependency on the scheduler library. time.sleep()
might be more reliable for long intervals as it doesn't rely on system-level time handling as much:
def call_repeatedly(interval, func, *args, **kwargs):
def loop():
while True:
func(*args, **kwargs)
time.sleep(interval)
threading.Thread(target=loop, daemon=True).start()
lock = threading.Lock()
in a local variable is not suitable for synchronizing access from multiple threads. I guess your actual code is different, but then again the code here is not representative. Please extract and provide a minimal reproducible example! – Ulrich Eckhardt Commented Feb 6 at 13:23why works that on a weaker raspberry pi 4
precisely because it's weaker so the chance of two threads executing at the same time is less. As Ulrich Eckhardt explained this code isn't locking anything because bothstopped
andlock
are local to the method. Every execution will get its own event and lock. – Panagiotis Kanavos Commented Feb 6 at 13:42