Skip to content

gloo-timer: TimeoutFuture::poll panics when oneshot Sender is dropped without sending #570

Description

@Eligioo

Describe the Bug

TimeoutFuture documents that it "will never resolve to Err" and encodes that belief in poll by calling .unwrap_throw(). This invariant does not hold. The receiver can legitimately yield Err(oneshot::Canceled), at which point unwrap_throw() throws.

Error: called `Result::unwrap_throw()` on an `Err` value
    at __wbindgen_throw
    at wasm_bindgen::throw_str
    at <gloo_timers::future::TimeoutFuture as core::future::future::Future>::poll

Steps to Reproduce

Under wasm-bindgen --weak-refs, the cleanup of resources can happen in different stages. With weak refs enabled, JS-side closures are reclaimed by the JS engine's GC rather than freed synchronously when the Rust side drops the Timeout.

  1. Rust drops a TimeoutFuture (e.g. a struct prop holding the timer is overwritten with a new timer).
  2. clearTimeout is called for the old timer.
  3. The Rust Timeout struct is dropped, but the Closure holding tx is not freed immediately — that's deferred to the next GC pass.
  4. Before the GC runs, the new TimeoutFuture is polled (advancing the async state machine), and the old rx is polled one final time.
  5. When the GC eventually finalizes the closure, tx is dropped without send() having been called. But by the time the GC runs, the rx may still be accessible and may get polled again.

Reference to tracking issue: nimiq/core-rs-albatross#3844

Expected Behavior

Don't work with the assumption the rx cannot fail when polled and handle the invariants properly.

Actual Behavior

An Err() is returned which is being unwrapped into a panic.

Activity

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

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions