Calling blocking code in coroutines

Sorry to dig up an old thread. I’m trying to understand how cancellations work in the case of blocking code in coroutines.

Ideally, cancellation of a job would interrupt the thread running the blocking code, or at least allow the blocking code to complete but ignore it’s results/exceptions. I tried using @elizarov 's second example from above, switching to a newSingleThreadContext but doing so causes the job to no longer be cancelable. Calling job.cancel() returns true but the coroutine keeps executing.

In trying to debug this, I tried using run along with suspendCancellableCoroutine but the outcome was the same.

Submitting the block to an executor has the behavior I expect:

suspend fun <T> runInExecutor(executor: Executor, block: () -> T): T = suspendCancellableCoroutine { cont ->
    executor.execute {
        try {
            cont.resume(block())
        } catch (e: Throwable) {
            if (!cont.isCompleted) cont.resumeWithException(e)
        }
    }
}

However, I can’t seem to figure out why the run() solution doesn’t work. Is run() thinking CommonPool and newSingleThreadContext are the same and not actually suspending?

Here’s a rather contrived example demonstrating what I’m talking about: Blocking coroutine behavior · GitHub