Skip to content

fix(basics): a helper timeout too long for a deadline is refused - #3141

Merged
gold-silver-copper merged 3 commits into
mainfrom
fix/helper-timeout-ceiling
Nov 8, 2026
Merged

gold-silver-copper merged 3 commits into
mainfrom
fix/helper-timeout-ceiling

Conversation

@gold-silver-copper

@gold-silver-copper gold-silver-copper commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

Description

A helper's time limit is the call's timeout, else [helpers] timeout_secs. Only 0 was refused. The runner computes each child's deadline as Instant::now().checked_add(timeout), and Process::run reads a None deadline as "no deadline", so a value too large to add to now (such as timeout: 18446744073709551615) gave the helper no time limit at all.

Now a timeout over a fixed ceiling is refused, naming the value and the ceiling, where 0 is refused: a call's timeout when the call is made (in timeout()), and timeout_secs when settings are read (a deserialize_with on the field, so the user learns at load time).

The ceiling is u32::MAX seconds (4294967295 s, about 136 years). It is fixed, not read from the clock: Instant holds at least an i64 or u64 count of seconds since an epoch near boot on every platform std supports (Linux, macOS, Windows), so adding 136 years to now always fits, whatever the uptime, and a value that passed at load also fits for a helper started later in a queue or chain. Any timeout a person means is far below it. The runner no longer reads a deadline that doesn't fit as "no deadline": should checked_add ever fail, the helper is refused before it starts.

Review round 1 changed this from a check against the clock (Instant::now().checked_add) at read time, which let a value just under the limit pass and then overflow for a helper started later, and moved with uptime.

What users see change

  • A helper call with a timeout too large to make a deadline (for example 18446744073709551615) is refused with a timeout of 18446744073709551615 s is over 4294967295 s, instead of running with no time limit. The ceiling is 4294967295 s (about 136 years); that value itself is accepted.
  • [helpers] timeout_secs over the ceiling (for example 4294967296) is refused when settings are read, with an error naming the value, as timeout_secs = 0 already is.
  • Ordinary timeouts (such as 7200) behave as before.

Tests

Bug Test (rig-basics) Fails on base with
A huge call timeout, or timeout_secs, means no deadline helpers::tests::a_timeout_too_long_for_a_deadline_is_refused a call's timeout too long for a deadline: Ok(18446744073709551615s) (the tests-only commit; round 1 extended the test to check the ceiling itself is accepted and 4294967296 is refused, for the call and for timeout_secs)

One existing test's doc changed on purpose: a_helpers_deadline_is_the_calls_timeout_or_the_setting said "however long", which is no longer true.

Changelog

  • (basics) A helper timeout, or [helpers] timeout_secs, over 4294967295 s (about 136 years) is refused naming the value instead of possibly meaning no time limit.

Migration

None

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Testing

  • The test fails on the test-only commit for the stated reason and passes on the head (box2, cargo nextest run -p rig-basics)
  • cargo xtask verify --affected --base origin/main (box2)

Checklist:

  • I have updated READMEs and Rust docs affected by this change
  • I have added tests that prove my fix is effective or that my feature works
  • I did not edit CHANGELOG.md or MIGRATING.md (they are generated at release)

Notes

Line deltas: production +24 / -4 (plugins/rig-basics/src/helpers.rs), tests +23 / -2.

Not verified: not driven in the real rig binary; macOS and Windows (CI runs Linux; the ceiling's fit on them is from std's Instant representation, not a run).

Follow-ups

None.

A helper call's `timeout`, or `[helpers] timeout_secs`, so large that
now plus it overflowed the clock made no deadline at all: the helper
could run forever. Such a value is now refused naming it, a call's
`timeout` when the call is made and `timeout_secs` when settings are
read, as 0 already is.
Checking a timeout against the clock when it is read let a value just
under the limit pass and overflow for a helper started later, and the
limit moved with uptime. A timeout is now refused past u32::MAX seconds,
about 136 years, which every platform's clock adds to now. A deadline
that still does not fit refuses the helper instead of meaning none.
@gold-silver-copper
gold-silver-copper added this pull request to the merge queue Nov 8, 2026
Merged via the queue into main with commit 2af21d0 Nov 8, 2026
17 checks passed
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

Successfully merging this pull request may close these issues.

1 participant