Skip to content

loop() uses time.monotonic(), resulting in unwanted behaviors #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gmparis opened this issue Sep 11, 2023 · 5 comments
Closed

loop() uses time.monotonic(), resulting in unwanted behaviors #176

gmparis opened this issue Sep 11, 2023 · 5 comments

Comments

@gmparis
Copy link

gmparis commented Sep 11, 2023

Use of time.monotonic() in loop() causes issues with pinging and specified timeout values greater than 0. This is due to the resolution of the float value returned by monotonic. After an amount of uptime, the time subtractions in the code will begin to result in 0.

@vladak
Copy link
Contributor

vladak commented Oct 25, 2023

Can you be more specific about which of the 2 subtractions in loop() is causing issues ? What was the timeout value ? What platform did you reproduce this on ?

@gmparis
Copy link
Author

gmparis commented Oct 25, 2023 via email

@vladak
Copy link
Contributor

vladak commented Oct 27, 2023

I see. According to my computations based on https://docs.circuitpython.org/en/latest/shared-bindings/time/#time.monotonic after some 24 days the counter will be increased only every second or so.

Wonder what the right solution is, given that:

  • time.monotonic_ns() (returns int) is not available on some architectures/microcontrollers according to the documentation
  • supervisor.ticks_ms() returns int however wraps around every couple of days and is also not available in CPython (which is used to run the tests and also used by some as a MQTT client library on regular computers)

@gmparis
Copy link
Author

gmparis commented Oct 27, 2023 via email

@vladak
Copy link
Contributor

vladak commented Oct 28, 2023

Perhaps not as big a dilemma as you imagine. What devices are suitable for using MQTT (i.e., have wireless or Ethernet) and do not support monotonic_ns()? The bottom line is that if the device locks up after a period of a few weeks, it is not good enough for any serious use. Even too frustrating for non-serious use. Better to just say MQTT is not supported on that device.

Thanks for pointing out that only networked boards need to be considered.

If I understand it correctly, time.monotonic_ns() uses Python long ints, so does not wrap around.

adafruit/circuitpython#519 has a comment about non long int builds for tiny devices such as Gemma or Trinket. These do not have any network connection AFAIK and there's probably not an add-on board to add it either. I am not faimilar with CircuitPython and Adafruit ecosystem enough to be able to tell what boards might actually be impacted (maybe Adafruit Feather M0 WiFi or such ?), however monotonic_ns() seems to be the way to go.

If there is anything that could have network but not long int build then there are several ways how to deal with this:

  • document this
  • detect the loss of precision and raise an exception
  • the above combined

which is pretty lame as the reaction to the exception should be a board reset.

Having the code that would switch based on call availability between a call that provides sufficiently consistent precision but wraps around and a call that has the required precision characterstics and does not wrap around but is not available on all networked boards sounds like a way to make the library too complex and fragile so I'd like to avoid it.

Maybe for a good measure add a __init__ code that would detect the lack of monotonic_ns() and raise some sort of runtime exception to prevent frustration. Or, if it's not available, go with monotonic() as the last resort. Again, the above bullet section applies. Or, raise the exception only if certain init parameter is not set (which would not be by default).

vladak added a commit to vladak/Adafruit_CircuitPython_MiniMQTT that referenced this issue Oct 30, 2023
otherwise fall back to time.monotonic() however only if forced

fixes adafruit#176
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants