# Using coroutine cancellation for custom cleanup / shutdown?

**URL:** <https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388>\
**Category:** Language Design\
**Created:** [November 4, 2021, 6:33pm UTC](https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388 "2021-11-04T18:33:16Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![crg7475](https://avatars.discourse-cdn.com/v4/letter/c/4bbf92/32.png) [@crg7475](https://discuss.kotlinlang.org/u/crg7475)\
**Post date:** [November 4, 2021, 6:33pm UTC](https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388/1 "2021-11-04T18:33:17Z")

</div>

Is it considered bad practice to catch `CancellationException`, do custom shutdown/cleanup code, and then rethrow the exception?

If I have a suspend function that performs some operation, and want a way to cancel that operation, I may need to perform some steps to rollback the partial changes performed by that operation. Is it OK to do that in a `CancellationException`? Or should cancellation procedures be left “untouched” as much as possible?

In the latter case, I can only imagine adding a separate “cancelOperation” function in the same API. Note that I was talking about an operation done by a suspend function, so the operation is done once that function no longer suspends. This means that I can’t just return some custom class that contains a “cancelOperation” function or a “dispose” function (COIL does the latter).

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [November 4, 2021, 7:21pm UTC](https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388/2 "2021-11-04T19:21:01Z")

</div>

Yes, exception handlers is exactly the way how clean up should be performed when using coroutines. Although, it probably makes more sense to use `finally` instead of `catch`. You don’t need to rethrow and you perform clean up for any exception, not only `CancellationException`.

[https://kotlinlang.org/docs/cancellation-and-timeouts.html#closing-resources-with-finally](https://kotlinlang.org/docs/cancellation-and-timeouts.html#closing-resources-with-finally)

---

<div class="post-metadata">

**Author:** ![crg7475](https://avatars.discourse-cdn.com/v4/letter/c/4bbf92/32.png) [@crg7475](https://discuss.kotlinlang.org/u/crg7475)\
**Post date:** [November 4, 2021, 7:46pm UTC](https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388/3 "2021-11-04T19:46:03Z")

</div>

Alright. Makes sense, thanks! I think there are cases where you do want to actually catch the exception though - if for example your function is comitting some changes to a persistent state, and mid-commit, a cancellation happens, then the partial commit needs to be rolled back - something you don’t normally do.

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [November 4, 2021, 8:45pm UTC](https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388/4 "2021-11-04T20:45:04Z")

</div>

Ahh, yes, you are right. Often clean up is different for success and failure paths. Still, we don’t need to target `CancellationException` specifically. Standard handling by catching `Throwable` will work just fine.

---

<div class="post-metadata">

**Author:** ![mtimmerm](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/mtimmerm/32/7160_2.png) [@mtimmerm](https://discuss.kotlinlang.org/u/mtimmerm)\
**Post date:** [November 5, 2021, 1:07am UTC](https://discuss.kotlinlang.org/t/using-coroutine-cancellation-for-custom-cleanup-shutdown/23388/5 "2021-11-05T01:07:19Z")

</div>

Generally, use a `finally` block for cleanup, to make an obvious guarantee that it happens no matter what.

For things like commit/rollback, commit at the end of the successful path and then set a variable like `committed=true`. Then in the `finally` block, roll back if `!committed`.

You usually only need to actually catch an exception if you want to log it, recover, rethrow it as something else, or something like that.
