microsoft / microsoft/cppwinrt
Bug: should_originate_on_cancel does not cancel certain awaiters or duplicated actions.
Nessuno ha ancora preso questa issue.
- Lingua principale
- C++
- Stelle
- 1.9k
- Fork
- 281
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
Version
3.0.260715.1
Summary
- #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_await get_cancellation_token();
cancel.enable_propagation();
cancel.originate_on_cancel(false);
while (true)
{
co_await RefreshAsync();
co_await resume_after(30s); // cancelled here -> timespan_awaiter::await_resume
} // throws hresult_canceled() -> originates
}
Expected behavior
No response
Actual behavior
No response
Additional comments
No response
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Traccia la gestione della cancellazione attraverso impl::check_status_canceled, await_adapter::await_resume, timespan_awaiter::await_resume e signal_awaiter::await_resume. Verifica che una cancellazione ripetuta non ripristini l’impostazione originate-on-cancel e che resume_after e resume_on_signal rispettino originate_on_cancel(false); aggiungi o aggiorna la copertura per gli scenari ripetuti ed elencati degli awaiter.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- cpp
- Ambito
- operating-systems
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Tranquilla
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 48/100