CNA-GAP-070: NetworkSession's Local, LocalWithLeaderboards and SystemLink Begin/End pairs are synchronous: Begin runs the callback and returns a completed result, and End does the work on the caller's thread

CNA snapshot c1c316b9  ·  Known Issues › Functional gaps  ·  source links pinned to c1c316b9

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit c1c316b9; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

For Local, LocalWithLeaderboards and SystemLink sessions, BeginCreate, BeginFind and BeginJoin run the callback inline and return a completed result; End* then blocks: 150 ms for a SystemLink Find, up to 5 s for a SystemLink Join.

Identifier
CNA-GAP-070
Category
Functional gap
Subsystem
Networking & gamer services
Status
Open
Verified against
CNA c1c316b9 (c1c316b9c7a846ce8002809c151fcd1af14942c9)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
Microsoft::Xna::Framework::Net::NetworkSession::BeginCreate/BeginFind/BeginJoin and the matching End* methods for Local, LocalWithLeaderboards and SystemLink sessions

Expected behaviour

XNA 4.0 (read from the decompiled Microsoft.Xna.Framework.Net assembly and its async dispatcher; not executed) registers each Begin* operation as pending: IsCompleted stays false until a dispatcher thread finishes it, the wait handle is signalled then, the AsyncCallback is queued to the thread pool, and End* returns the finished result.

Actual behaviour at TARGET

In NetworkSession.cpp a NetworkSessionAction starts complete (IsCompleted true, wait handle signalled, CompletedSynchronously true). For every session type except PlayerMatch and Ranked, BeginCreate, BeginFind and BeginJoin invoke the AsyncCallback inline (InvokeActiveActionCallback) before returning. The work then runs in End* on the caller's thread. On native builds, EndFind waits the fixed 150 ms SystemLink discovery window, and EndJoin pumps the joined session for up to 5 s until the host's welcome arrives. A game that polls IsCompleted every frame and calls End* when it turns true therefore stalls there. Service-backed PlayerMatch/Ranked Create, Find and Join, and BeginJoinInvited, are genuinely pending (QueueOnlineSession, QueueServiceSearch): IsCompleted stays false until the CNA service answers, so they are not part of this entry.

Source locations

Evidence

Read at c1c316b9; nothing executed. The published deep dive on network sessions records the completed-at-construction behaviour as an implementation oddity; this entry records its consequence for callers who port XNA's asynchronous pattern. Reported as a narrow restore by the D2 dismissal reviewer, who had confirmed that CompletedSynchronously being false matches XNA, and re-verified by the orchestrator.

Re-verified at b0e97bb1: b7754e45f (GS-007e2b) made service-backed PlayerMatch and Ranked Create, Find and Join, and BeginJoinInvited, genuinely pending; Local, LocalWithLeaderboards and SystemLink Begin calls still complete inline, now reporting CompletedSynchronously true. Not executed.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

NetworkSessionTests.BeginCreateInvokesCallbackExactlyOnceWithCorrectIdentity pins the inline callback; no test measures the time EndFind or EndJoin block.

Blast radius

Games and samples that start a Begin* operation and keep rendering while they wait: with CNA the wait moves into End*, so the frame that calls it stalls for up to the discovery window or the join timeout.

Workaround

Call End* from a worker thread or accept the stall on a loading screen; do not call it from the frame loop.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.