microsoft / microsoft/cppwinrt

Bug: should_originate_on_cancel does not cancel certain awaiters or duplicated actions.

Aperta
#1,617 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

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
  1. #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

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. 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

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.