CNA-BUG-157: HttpNotificationChannel::Close and the channel destructor block indefinitely while a connected peer sends nothing
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 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
The single listener thread reads each accepted connection with a blocking recv and no timeout; Close shuts down only the listening socket and then joins that thread, so a silent peer stalls Close and the destructor.
- Identifier
CNA-BUG-157- Category
- Bug
- Subsystem
- Networking & gamer services
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Medium (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- Microsoft::Phone::Notification::HttpNotificationChannel::Close() and ~HttpNotificationChannel()
Expected behaviour
The header documents Close as “Stops listening and releases the address” and the destructor as closing the channel. Close's own comment explains that it shuts the listening socket down precisely so the worker is not left parked in accept(). Closing a channel, including at game shutdown, should return promptly.
Actual behaviour at TARGET
Listen handles one connection at a time and calls ReadRequestBody, whose recv calls block with no SO_RCVTIMEO, poll or deadline. Close clears listening_, calls shutdown on and closes listenSocket_ only, then joins the worker. The accepted connection the worker is blocked on is not touched, so the join waits until that peer finishes its header block or closes. While it waits, later connections queue in the backlog of 4 and nothing is delivered. A connected peer that stays silent therefore makes Close(), and the destructor that calls it, wait without bound.
Source locations
modules/phone/src/HttpNotificationChannel.cpp— Listen, ReadRequestBody (blocking recv, no timeout), Close (shutdown of the listening socket only, then join)modules/phone/include/Microsoft/Phone/Notification/HttpNotificationChannel.hpp— Close and destructor documentation
Evidence
Checked by reading HttpNotificationChannel.cpp at 009d40f5 (unchanged since the earlier recorded pin). The wait follows mechanically from a blocking recv on a socket nothing shuts down; not executed.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
Every client in the notification tests sends a complete request and closes; no test holds a connection open across Close().
Regression test
A test that connects a raw socket to an open channel, sends nothing, and calls Close() under a deadline (for example two seconds on a watchdog thread). A fix can give accepted connections a receive timeout, poll the listening and the accepted socket together with a wake-up descriptor, or have Close shut down the in-flight connection too.
Blast radius
Processes that opened a channel: an explicit Close or the shutdown path can wait, and other pushes are held while the worker waits. Only peers on the same host can connect (the channel binds loopback).
Workaround
No workaround is known.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Maintainer workflow
- I need to debug shutdown and lifetime behavior
- Known issues
- Bug index