# Evaluating the state of the art of Python asyncio with the "Cancellation in Systems" paper

**URL:** <https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350>\
**Category:** Async-SIG\
**Created:** [August 21, 2022, 4:05am UTC](https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350 "2022-08-21T04:05:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![achimnol](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/achimnol/32/28061_2.png) [@achimnol](https://discuss.python.org/u/achimnol)\
**Post date:** [August 21, 2022, 4:05am UTC](https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350/1 "2022-08-21T04:05:57Z")

</div>

This thread is a more detailed comparison of asyncio with [the paper](https://www.usenix.org/conference/osdi22/presentation/sethi) I mentioned in [a prior thread](https://discuss.python.org/t/about-the-task-cancel-messages/17122/2). I’m not going to insist to add something right now to asyncio based on this paper, but just want to share how we are doing well and potential points to improve in the future.

Although the paper does not mention Python asyncio at all but comes with case analysis of cancellation-related bugs in other languages (C#, Java, Go) and applications (Cassandra, Hadoop, etc.), the meaning of the paper is that it provides _a structured base to discuss_ what kinds of issues should be considered when we are going to improve asyncio.

TLDR: Thanks to the core contributors and the community, Python asyncio has constructed a fairly good baseline for writing complex concurrent applications. I think it would be insightful to retrospect asyncio’s achievements with the arguments of the paper as it serves as a reference point.

| Reference in the paper | Short desc. | Status of asyncio |
| --- | --- | --- |
| §5.1.2, §5.1.3 | Broken trigger checks, Excess cancel (unexpected overlapping of tasks without cancelling previously launched ones which may happen with async timers) | ⚠ No intrinsic utility for timers or periodic tasks\[1\] – it may be controversial to include timer APIs in asyncio, though. / ✅ Guaranteeing scoped cancellation in complex task trees is partly covered with `TaskGroup`. |
| §5.2.1 | Untimely delivery - cancel race | ⚠ `asyncio.shield()` could be used to circumvent duplicate cancel requests and protect ongoing cancellations\[2\], but still the event loop still unexpectedly shuts down all ongoing tasks regardless whether they are shielded or not. |
| §5.2.1 | Untimely delivery - late polling | ✅ asyncio is based on inherently “cooperative” coroutines and it should be fine as long as all dependencies are async-aware (i.e., no hidden blocking calls) / 🤔 Programmer’s caution is still the main mean of preventing this issue and this is the reason of difficulty when writing asyncio apps. |
| §5.3.1, §5.3.2 | Cacnel not checked/carried out | ✅ The situation has improved a lot after promoting `asyncio.CancelledError` as `BaseException` (since Python 3.8) / ⚠ A structured way of ensuring clean-up of long-running tasks are still missing (particularly `TaskGroup`)\[3\] |
| §5.4 | Cancel mechanisms - cancellable task interface | ✅ `asyncio.Task` and `asyncio.Future` |
| §5.4 | Cancel mechanisms - uninterruptible interface | ✅ `asyncio.shield()` partly corresponds to this, in that it blocks the cancellation signal. |
| §5.4, §5.3.3 | Cancel mechanisms - task dependency tracking | ✅ `asyncio.TaskGroup` 🎉 |

* * *

1. `aiotools`’ timer module has `TimerDelayPolicy` to express “cancel prior task if it’s not complete until the next wait interval finishes”. 

2. I have an experience that I had to shield all database transactions in web request handlers because cancelling in the middle of ` __aexit__ ()` of `aiopg`’s transaction blocks had caused unreleased database connections and exhaustion of the connection pool. 

3. This is why I’ve suggested `PersistentTaskGroup`, to cover the use case of `asyncio.gather(..., return_exceptions=True)`.

---

<div class="post-metadata">

**Author:** ![guido](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/guido/32/21_2.png) [@guido](https://discuss.python.org/u/guido)\
**Post date:** [August 22, 2022, 2:30am UTC](https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350/2 "2022-08-22T02:30:36Z")

</div>

What is “sota” (a word you used in the thread title)?

Looking at the paper a bit more it seems heavily focused on cancellation in thread-based systems, where race conditions are more common than in asyncio.

You claim that asyncio doesn’t have a utility for timers. I wonder if you aren’t aware of [`call_later`](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_later) or if you have some reason to discount it? It would seem to be simple enough to create a periodic task from this.

Regarding [your own timer code](https://github.com/achimnol/aiotools/blob/main/src/aiotools/timer.py#L31), it seems a bit over-complicated: if the delay policy is `CANCEL`, `fired_tasks` will have 0 or 1 element, while if the delay policy is `DEFAULT`, `fired_tasks` is never needed. (Maybe this is a remnant of an earlier version of your code?) In any case there seem to be different ways to time a cat. 🙂

Regarding the issue you mention about `shield()` not protecting against loop shutdown, maybe you can just file an issue about that? (With a small example that reproduces the problem, please.)

---

<div class="post-metadata">

**Author:** ![corona10](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/corona10/32/9943_2.png) [@corona10](https://discuss.python.org/u/corona10)\
**Post date:** [August 23, 2022, 10:58am UTC](https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350/3 "2022-08-23T10:58:25Z")

</div>

> [@guido](#):
>
> What is “sota” (a word you used in the thread title)?

He seems to write it in the meaning of State-Of-The-Art.

---

<div class="post-metadata">

**Author:** ![achimnol](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/achimnol/32/28061_2.png) [@achimnol](https://discuss.python.org/u/achimnol)\
**Post date:** [August 23, 2022, 1:11pm UTC](https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350/4 "2022-08-23T13:11:26Z")

</div>

As @corona10 clarified, I meant SOTA (state-of-the-art). Sorry for confusion.

> [@guido](#):
>
> You claim that asyncio doesn’t have a utility for timers. I wonder if you aren’t aware of [`call_later`](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_later) or if you have some reason to discount it? It would seem to be simple enough to create a periodic task from this.
> 
> Regarding [your own timer code](https://github.com/achimnol/aiotools/blob/main/src/aiotools/timer.py#L31), it seems a bit over-complicated: if the delay policy is `CANCEL`, `fired_tasks` will have 0 or 1 element, while if the delay policy is `DEFAULT`, `fired_tasks` is never needed. (Maybe this is a remnant of an earlier version of your code?) In any case there seem to be different ways to time a cat. 🙂

Thanks for having a look at it. That code is a very old, relatively not updated code. 🙈  
I had a production issue that accumulated an infinite number of tasks, causing server unresponsiveness, when each task created upon the timer tick takes more time than the interval of the timer. That’s why I wrote this rudimentary abstraction. I just want to share my experience with asyncio in production systems.\[1\]

I’m not directly claiming that “we need to add some new abstraction for timers _right now_”, but this is just **a provoking of ideas** by comparing what we have in asyncio with a survey paper which highlights the importance of careful handling of cancellations. An academic paper serves as a good reference point.

> [@guido](#):
>
> Looking at the paper a bit more it seems heavily focused on cancellation in thread-based systems, where race conditions are more common than in asyncio.

Yes, that’s true. I also wanted to see more discussions in the paper related with coroutine-based systems such as C#, Kotlin, Python, and Javascript. But still, I think the nature of cancellation issues discussed in the paper, such as what kind of abstractions and supports are required from the language/runtime/library, reflects the same concerns about task cancellation in asyncio. The paper is more about cancellation, not race condition issues.

* * *

1. My main project, Backend.AI, is now 7 years old and earning real money from enterprise customers from multiple countries, and it heavily relies on the asyncio ecosystem.

---

<div class="post-metadata">

**Author:** ![guido](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/guido/32/21_2.png) [@guido](https://discuss.python.org/u/guido)\
**Post date:** [August 23, 2022, 5:10pm UTC](https://discuss.python.org/t/evaluating-the-state-of-the-art-of-python-asyncio-with-the-cancellation-in-systems-paper/18350/5 "2022-08-23T17:10:57Z")

</div>

Okay, I’ve updated the title yet again (I haven’t seen that acronym ever before) but also, I think I’ve given you all the discussion I have to give. I’ll leave it to others to continue the discussion.
