I am running into a problem where I don't really u...
# coroutines
d
I am running into a problem where I don't really understand what is going on. I traced it down to this part of the code:
Copy code
val device = withTimeout(Duration.parse("1s")) {
    println("before filestore").       // is printed
    val tmp = path.fileStore().name() // seems to freeze here
    println("Filestore name: $tmp")   // not printed
    tmp
}
The execution stops after
before filestore
is printed. Unfortunately, it runs on a machine where I can't just attach a remote debugger. How can the execution freeze at that point? I would expect to run into a
TimeoutCancellationException
after one second. However, that does not happen.
r
You might be running into the issue where TimeoutCancellationException extends CancellationException which means that coroutines treat it specially
d
Good point. Let me surround that with a
try
-
catch
and see if the exception occurs
I replaced it with that:
Copy code
val device: String = try {
    withTimeout(Duration.parse("1s")) {
        println("before filestore")
        val tmp = path.fileStore().name()
        println("Filestore name: $tmp")
        tmp
    }
} catch (e: TimeoutCancellationException) {
    e.printStackTrace()
    "invalid"
}
Execution does not seem to run into the
catch
-clause.
r
Cancellation is cooperative - assuming filestore() and/or name() are blocking (not suspending) functions they won't react to the coroutine being cancelled because they're not aware of/ expecting it. Because of structured concurrency the coroutine can't complete until they return.
☝️ 1
r
ok, just looked at Path.fileStore, it's not a coroutine so it doesn't suspend so the Duration wouldn't affect it anyway?
I don't know if it is Interruptible, if it is then you can wrap path.fileStore() in
runInterruptable
d
it seems like it is not interruptible and just blocks
Ok, my solution is to work around the problem. It seems like
Path.filestore()
seems to block indefinitely on a broken symbolic link (for whatever reason). I am checking for that corner case and avoid it. I learned from this that there is no point in wrapping filesystem IO operations with coroutines as they would just block anyway and there is no way to cover for this in the cooperative approach of coroutines.
e
you might want to use runInterruptible - it translates coroutine cancellation into Java thread interruption, which interrupts most Java I/O
⬆️ 1
e
Did not know about
runInterruptible
, nice one!