Another question :slightly_smiling_face: Why is th...
# coroutines
v
Another question 🙂 Why is this warning? As I understand, it's the recommended way to wrap IO-bound blocking calls with
<http://Dispatchers.IO|Dispatchers.IO>
p
it’s blocking thread, but is it cancellable?
s
I think the linting that produces this warning is not able to look a few steps up the hierarchy and see the
<http://Dispatchers.IO|Dispatchers.IO>
there. Move the call to `withContext down to just before/around calling
process.waitFor
should get rid of the warning. Or otherwise, just suppress the warning 🙂
v
same
hmm. Is there a documentation for this warning? The algorithm?
waitFor
is not cancellable.
It's just throw if timed out
s
This lint warning is produced if the call is declared to be able to throw an IOException and this call is not directly wrapped inside a
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
call.
It produces false warnings if the dispatcher was switched to the IO one earlier and if your code injects the dispatchers and not ‘hard-code’ the Dispacthers.IO. I has nothing to do with being cancellable or not.
👌 1
v
BTW, maybe there's a well behaving, idiomatic way to run a process, with timeout and cancellation?
I'm using val process = ProcessBuilder(*parts.toTypedArray())   .directory(workingDir)   .redirectOutput(ProcessBuilder.Redirect.PIPE)   .redirectError(ProcessBuilder.Redirect.PIPE)   .start()
s
You can’t cancel a blocking call. At best you can interrupt the thread that is blocked but that can be dangerous
You can cancel a suspending call, though, but that is different 🙂
v
Yes, I understand.
m
Do you really need the separate call to
withContext
? Can't you just do this:
Copy code
launch(<http://Dispatchers.IO|Dispatchers.IO>) {
    process.waitFor(....)
}
👆🏻 1
v
I think about a process runner, which, being cancelled, kill the process or something like this.
@marstran aha! The warning has gone.
But I think
withContext
is what is recommended to use, isn't it?
s
If you want to cancel something:
Copy code
suspendCancellableCoroutine<Unit> { cont ->
    val handle = startBlockingProcess(....)
    cont.invokeOnCancelation { handle.cancel() }
    cont.resume(Unit)
}
(assuming
handle
represents a process that can be cancelled by calling
cancel()
or something similar on it)
v
aha. I just read about this function yesterday 🙂
thanks.
s
You may need to do
handle.awaitResult()
or
handle.join()
or what-ever would be the correct function name, just before calling
cont.resume(Unit)
v
Should I handle exceptions inside it?
s
Yup, catch them and do
cont.resumeWithException(e)
v
ok
s
But this depends on how you model your app’s data model. You can catch the exception and then handled it by returning an error-value instead (
cont.resume(errorData)
)
v
got it