Skip to content

[Tracking]: Time handling: scattered millis() #11281

Description

@NomDeTom

TLDR: millis() deadline comparisons wrap at 49.7 days.

Draft rollup PR here: #11291

millis() returns a uint32_t that wraps every ~49.7 days. The firmware mostly handles this correctly — Throttle::isWithinTimespanMs() uses unsigned elapsed-since arithmetic and is used at 94 call sites, and the OSThread scheduler is rollover-safe inside the vendored ArduinoThread library. The problem is roughly 17 places that bypass both, storing a future deadline and comparing it directly against millis(). Those silently misbehave across the wrap: pending work either stalls until the counter catches up, or the whole queue fires at once.

Routers and infrastructure nodes stay up for months, so this is reachable in normal operation. The affected sites include reboot and shutdown scheduling (Power.cpp), the 12-hour Ethernet NTP renew (ethClient.cpp), GPS fix-hold and timeouts, retransmission timing (NextHopRouter.cpp), notification banners, and several touch-suppression windows. The same feature sometimes exists twice with only one version correct: WiFi NTP renewal uses Throttle properly, while the Ethernet path hand-rolls a deadline and is broken.

This is an adoption problem, not a design problem — the correct helper already exists and dominates usage. One hazard blocks a mechanical fix: several of these variables overload their value with a sentinel (0 for inactive, -1/UINT32_MAX in Power.cpp and ExternalNotificationModule.cpp). Under today's naive comparison -1 reads as "never fire"; under any corrected comparison it becomes "expired 49 days ago", causing a reboot loop. The sentinels must be untangled first. A CI guard rejecting new millis() > deadline comparisons would stop the list growing again.

Open PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttech debtCode or lib references that are not up to date or propper standards

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions