CNA-BUG-161: A handler that throws during HttpNotificationChannel::DispatchPendingNotificationsEXT discards every remaining notification of that batch
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.
DispatchPendingNotificationsEXT moves the whole queue into a local vector before raising; an exception from a HttpNotificationReceived handler propagates and destroys the notifications not yet raised.
- Identifier
CNA-BUG-161- Category
- Bug
- Subsystem
- Networking & gamer services
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (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::DispatchPendingNotificationsEXT() and HttpNotificationReceived
Expected behaviour
The method is documented as “Raises the events of every notification that has arrived.” A notification that arrived but had not been raised when an earlier handler threw should not disappear: a later call should still raise it, or the method should document that a throwing handler loses the batch.
Actual behaviour at TARGET
The method swaps pending_ into a local vector under mutex_, releases the lock and raises HttpNotificationReceived once per body. Sharp Runtime's EventHandler::Raise invokes handlers without catching, so the first exception leaves the loop and the local vector, holding every body after the throwing one, is destroyed. The next dispatch sees only notifications that arrived after the swap.
Source locations
modules/phone/src/HttpNotificationChannel.cpp— DispatchPendingNotificationsEXT (swap, then raise loop)
Evidence
Checked by reading HttpNotificationChannel.cpp at 009d40f5 and System::EventHandler::Raise in sharp-runtime next @ 41b918c9 (iterates a snapshot, no catch; not pinned by TARGET). Not executed. That the other handlers of the throwing notification are skipped is ordinary multicast-delegate behaviour and not part of this entry.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
NothingIsRaisedUntilTheGameAsksForIt and WhatAServicePostsArrivesAsANotification use handlers that do not throw.
Regression test
Queue three notifications, subscribe a handler that throws on the first, catch the exception around the dispatch, dispatch again, and require the other two to be raised.
Blast radius
Ports whose notification handlers can throw; when only one notification is pending per dispatch nothing further is lost.
Workaround
Catch exceptions inside HttpNotificationReceived handlers.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Maintainer workflow
- Thread and callback map
- Known issues
- Bug index