Rewrite code to avoid leaking?

Hello,
I have the following code:

val conn = withContext(Dispatchers.IO) {
	dataSource.connection
}

conn.use {
	// ...
}

The trouble is, if this coroutine is canceled, conn will not be closed.

How can I rewrite code to avoid this? I have to acquire the connection on the IO thread.

Why do you think it won’t be closed? Do you mean cancelling when being inside use { ... }?

@broot No, if it’s canceled from outside while on line 2, Kotlin will produce exception while switching context.

Ok, it makes sense. One solution would be to do something like:

val ctx = coroutineContext

withContext(Dispatchers.IO) {
    dataSource.connection.use { conn ->
        withContext(ctx) {
            ...
        }
    }
}

But maybe there is a better way to do this.

1 Like

Thanks! that’s pretty clever

Caching the entire context and then switching back to it could cause some really awkward results depending on the other code involved. Passing Job into withContext bypasses normal structured concurrency behavior.

Each call to withContext basically creates a new child Job. withContext(ctx) is creating a Job that is a sibling, not child, of the withContext(Dispatchers.IO) created Job.

I suggest limiting the cached context to just the part you care about:

val ctx = coroutineContext[ContinuationInterceptor]
4 Likes

Good point. I was thinking mostly about using a dispatcher from the outer scope, but I missed the fact that the context is actually much more than that.