MaineKuehn/usim

async Task cancellation

Opened this issue · 1 comments

Short description of the feature
Cancelling a task currently a) allows the task to delay/ignore the cancellation and b) does not wait for completion. This means the cancelling task has to manually account for shutdown (e.g. MatterMiners/lapis#80).

Instead, we should offer an API that cancels a task and waits for completion. Notably, our internal, non-async API (Task.__close__) relies on prompt and successful termination.

Describe the solution you'd like
A public, asynchronous method for immediate shutdown. Roughly equivalent to:

class Task:
    ...

    async def terminate(self):
        self.__cancel__()
        await self.done

I'm still not 100% sure if we should use Coroutine.close(via .__close__) or add a cancellation (like .cancel currently does). close has guaranteed semantics, but allows no async action by the Task. A cancellation may be easier to handle in the activity, but requires a check for promptness.

For reference, asyncio is about to introduce Task groups and (slightly) changes cancellation semantics as a result. This adds cancellation as an actively tracked feature of tasks.

An asyncio Task is considered "being cancelled" once task.cancel() is called. Iff the task catches the cancel exception, the task still counts as "being cancelled" unless task.uncancel() is called.


It could be worthwhile to have the async cancellation work similarly:

  • .cancel() the task, but do not __close__() it
  • await that the task is .done or .uncancelled()
  • return whether the task is done?

I don't think promptness is something we should enforce, since it is difficult to define and detect.