Skip to content

contrib/timer-wheel: always-false idx < 0 disables the past-expiry branch (-Wtype-limits) #4770

Open

Description

@ThalesBarretto

__gf_tw_add_timer() (contrib/timer-wheel/timer-wheel.c:59) classifies a timer by
idx = expires - base->timer_sec, where idx is unsigned long. The branch meant to
catch an expiry already in the past tests idx < 0 — always false for an unsigned value:

contrib/timer-wheel/timer-wheel.c:59:24: warning: comparison of unsigned expression
    in '< 0' is always false [-Wtype-limits]
   59 |         } else if (idx < 0) {
      |                        ^

Two consequences:

  1. The warning, on every build under -Wextra.
  2. A dead branch. An already-past / expires == now timer has idx wrapped near
    ULONG_MAX, so it misses all four idx < SIZE buckets and falls through to the final
    else → tv5, where it is bucketed by expires bits — firing up to a full wheel
    period late instead of from tv1 on the next tick.

The wheel is a port of the pre-4.8 Linux cascading timer wheel (kernel/time/timer.c,
__internal_add_timer), which guards the same branch with (signed long) idx < 0 to
detect the unsigned wrap. The cast was dropped in the port.

Impact: latent, not a live regression. Every insert path converts a relative timeout
to absolute before bucketing — timer->expires += base->timer_sec in gf_tw_add_timer(),
expires + base->timer_sec in gf_tw_mod_timer() / gf_tw_mod_timer_pending() — so
idx >= 0 for every current caller (posix janitor, bit-rot, leases, nl-cache). The value
here is silencing the warning and restoring the intended past-expiry safety net.

Suggested fix (one line) — restore the signed cast:

-        } else if (idx < 0) {
+        } else if ((long)idx < 0) {

Distinct from #4740 (the fls() / BITS_PER_LONG leftovers of 1626dee); this
idx < 0 predates that commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions