Skip to content

Harden on_broadcast_ready against stale consume-announced terminal callbacks #50

Description

@coderabbitai

Summary

In src/moq-source.cpp, moq_source_start_consume now calls moq_origin_consume_announced and stores the returned task handle in ctx->consume_announced_task. The terminal callback on_broadcast_ready (broadcast <= 0) unconditionally clears ctx->consume_announced_task, and the success path (broadcast > 0) reads ctx->generation at callback time rather than validating against the generation the task was created for.

Problem

If a reconnect happens while an older consume-announced task is still winding down, a late terminal callback from that stale task can clear the newer task's handle in ctx->consume_announced_task, or (on the success path) attach a broadcast handle intended for an old generation to the current generation state.

Impact

Bounded: each task holds its own ctx reference (via subscription_ref), so there is no use-after-free. The only effect is that the newer wait loses its proactive moq_origin_consume_announced_close() on disconnect and instead resolves naturally when the origin is torn down; the existing refs timeout in moq_source_destroy still bounds teardown. The happy path is unaffected.

Proposed fix

Thread per-task state (task token + expected generation) through to on_broadcast_ready, and have the callback verify the callback still corresponds to the current task/generation before mutating ctx->consume_announced_task or ctx->consume. This likely also touches the similar generation-check pattern used in on_session_status and on_catalog for consistency.

Affected areas

  • src/moq-source.cpp: moq_source_start_consume, on_broadcast_ready, moq_source struct (task/generation bookkeeping)

Acceptance criteria

  • A stale terminal callback from a closed/replaced consume-announced task cannot clear a newer ctx->consume_announced_task handle.
  • A stale success callback (broadcast > 0) cannot attach its handle to the wrong generation.
  • No regression to the existing reconnect/teardown ref-counting and bounded-wait behavior.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions