You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remove throwing/originating errors in expected scenarios (Lookup/TryLookup and Cancel) #1512 introduced the setter originate_on_cancel and getter should_originate_on_cancel. The await_resume task would call originate_on_cancel (the setter) to check whether to RoOriginate the call. This is a bug, because the setter has a side effect. Its parameter defaults to true, so each call does std::exchange(m_originate_on_cancel, true): it returns the previous value, so the first check behaved correctly, and then wrote the flag back to true. Every later cancellation on that same promise originated again. A test that cancels only once passes even with the bug present.
IAsyncAction DoWork(HANDLE ready)
{
auto cancel = co_await get_cancellation_token();
cancel.originate_on_cancel(false); // "don't debug spew when I'm cancelled"
co_await resume_on_signal(ready); // If cancelled before `ready`, doesn't originate.
// The first Cancel() consumes the opt-out, re-arms the flag
co_await CleanupAsync(); // If cancelled after, then the next co_await will
// call Cancel() again, and since should_originate is true now
// it will Originate, thus causing the debug spew.
}
In addition, there is a missing scenario in the previous PR, it did not account for winrt::resume_after, winrt::resume_on_signal, and
These three awaiter resume paths also threw hresult_canceled unconditionally, so originate_on_cancel(false) had no effect on them at all: impl::check_status_canceled (reached from await_adapter::await_resume for any coroutine awaiting a WinRT async that completes Canceled), timespan_awaiter::await_resume (resume_after) and signal_awaiter::await_resume (resume_on_signal).
Reproducible example
IAsyncAction PollStatusAsync()
{
auto cancel = co_awaitget_cancellation_token();
cancel.enable_propagation();
cancel.originate_on_cancel(false);
while (true)
{
co_awaitRefreshAsync();
co_awaitresume_after(30s); // cancelled here -> timespan_awaiter::await_resume
} // throws hresult_canceled() -> originates
}
Version
3.0.260715.1
Summary
IAsyncAction DoWork(HANDLE ready)
{
auto cancel = co_await get_cancellation_token();
cancel.originate_on_cancel(false); // "don't debug spew when I'm cancelled"
}
In addition, there is a missing scenario in the previous PR, it did not account for winrt::resume_after, winrt::resume_on_signal, and
These three awaiter resume paths also threw hresult_canceled unconditionally, so originate_on_cancel(false) had no effect on them at all: impl::check_status_canceled (reached from await_adapter::await_resume for any coroutine awaiting a WinRT async that completes Canceled), timespan_awaiter::await_resume (resume_after) and signal_awaiter::await_resume (resume_on_signal).
Reproducible example
Expected behavior
No response
Actual behavior
No response
Additional comments
No response