Skip to content

wasm: concurrent first joins of the same topic can return a handle with dead subscription channels #97

Description

@pvg13

Problem

join_group/join_group_with_key are idempotent per user_topic via the client's handle registry, but the registry entry is inserted only after the store-open .await completes. Two overlapping, un-awaited first joins of the same topic on the single-threaded wasm executor therefore both pass the registry-miss fast-path, both derive/build a WebGroupInit (each with its own broadcast channels), and both send Command::JoinGroup.

The engine's groups.contains_key guard correctly keeps the FIRST init and makes the second a no-op ack — group state is never clobbered, and writes from either handle work (they route by topic through the command channel). But the second caller's WebGroupHandle holds inbound_tx/resolved_tx senders the engine never publishes to: its subscribe()/subscribe_resolved() streams are silently dead. The registry ends up holding whichever handle inserted last, so even client.group(topic) can return the dead-channel handle.

Not reachable with typical sequential/awaited usage (the Dioxus flow awaits each join); requires two un-awaited joins of the same brand-new topic in one tick. Auto-rejoined groups are unaffected (built in one synchronous pass).

Fix sketch

After the engine ack in join_group_inner, re-check the registry and return the existing entry if one appeared, instead of inserting unconditionally. Alternative: have the JoinGroup ack carry back the channels of the group the engine actually kept, and build the returned handle from those.

Found during the #93 review; see web_engine.rs join_group_inner (registry insert after the awaits) and the engine's JoinGroup handler (contains_key guard).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:lowEdge case or minor impact

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions