Skip to content

backgroundCompletion waits for thread exit, not task.return; immortal spawned futures make an idle-exited lift never resolve #313

Description

@lannbot

backgroundCompletion (#310) resolves an idle-exited async lift on Task.onFinished — the moment the task's last thread unregisters. For a callback-ABI task that keeps spawned futures alive for the instance's life (an event loop, a driver, an accept loop — wit-bindgen spawn_local from within the export), that moment never comes. So a lift that goes idle before task.return and is later woken by another export call does task.return, has its results captured (resolvedSeen true, resolved set), and the host's Promise still never settles.

The normal (non-idle) path does not require threads to drain: driveDone = resolvedSeen && !midWasmCall() && !hopParked(). The idle path should answer on the same event — the task's resolve callback (the (result) => { resolved = result; resolvedSeen = true } seam the lift already owns), deferred to a point where no wasm call of this task is in flight — rather than on thread exit. Thread drain is relevant to nothing the host is waiting for.

Not hit by polyvisor today (its exports that spawn immortal futures return before idling); found while fixing #312, whose regression misrouted a done exit into this path and so made the hang visible. Repro shape: long-poll.wat's next plus a second thread that returns WAIT on a never-fired waitable set before task.return.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions