https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Martin Devillers

12/18/2018, 10:11 AM
Do coroutines safely prevent memory leaks? I’d assume so, but if that’s the case I think that it would be a good idea to state it more explicitly in the documentation.
In this example, would the activity be leaked after leaving it?
g

gildor

12/18/2018, 10:17 AM
Of course it will leak
you cannot cancel non-cancellable operation
and yeah, coroutines did everything what is possible in this case to avoid leak. But because you use blocking code which impossible to cancel there is no way to avoid leak
m

Martin Devillers

12/18/2018, 10:18 AM
I agree, the inner coroutine started by
withContext
can’t be cancelled. But the coroutine started by
launch
can.
Since it’s just being suspended by waiting for the result from
withContext
g

gildor

12/18/2018, 10:19 AM
Yes, and it will be cancelled, but because code is blocking, there is no way to return and cleanup
m

Martin Devillers

12/18/2018, 10:20 AM
There is definitely a way, it’s not impossible. The continuation referenced by the
withContext
coroutine would just have to be null, since it’s cancelled anyways.
g

gildor

12/18/2018, 10:21 AM
But in this case coroutine will leak
also what if you want to cleanup, like use try/catch
I may be wrong of course probably better to ask @elizarov
but not sure that there is a way to make such badly written code safe without breaking contract
m

Martin Devillers

12/18/2018, 10:23 AM
Sure, thanks for your input 🙂 You have a good point with the cleanup
g

gildor

12/18/2018, 10:24 AM
just to clarify I mean:
Copy code
launch {
try {  
            val message = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
                Thread.sleep(Long.MAX_VALUE)
                "Hello World!"
            }
        }
} finally {
   //do some required operation in any case
}
}
👍 1
e

elizarov

12/18/2018, 11:02 AM
I fully support what @gildor says. We cannot just “abandon” coroutines on cancellation, because they might need to do cleanup, so there is no way to prevent leaks if you have non-cancellable operation. Coroutines are doing their best to avoid leaks, but cancellation is cooperative, so you have to also do your part — make sure all your operations are cancelable.
👍 1
r

Rohan Maity

12/18/2018, 11:22 AM
Please correct me if I am wrong Is the Reason being there is leak because withContext was totally started with different Context. So it's independent of launch scope. Therefore even if launch is cancelled but withContext work is still in progress.
m

Martin Devillers

12/18/2018, 12:11 PM
@Rohan Maity No,
withContext
inherits the parent job from
launch
, so it will receive the cancellation. The issue is that the cancellation won’t do anything because the coroutine doesn’t handle it. This coroutine will therefore continue running, and will keep the reference to the activity through its continuation.
r

Rohan Maity

12/18/2018, 12:45 PM
It is said "you can't cancel the non cancellable operation". So what part makes the non cancellable operation?
g

gildor

12/18/2018, 12:49 PM
Thread.sleep is blocking operation that cannot be cancelled
💯 3
s

streetsofboston

12/18/2018, 12:52 PM
I understand the routine inside
withContext
does not cancel and keeps running. But this block of code does not have a reference to anything in the Activity. This block of code doesn't leak. But the
launch
has a call to
this@CoroutineActivity.findViewById
which can leak the Activity. Does a coroutine not cancel if one of its child-coroutines are not cancelled? Could a cancel request interrupt a running Thread?
g

gildor

12/18/2018, 1:08 PM
There is no way to interrupt threads on JVM starting from Java 1.2 (or even 1.1)
stop method just doesn't work
There is interrupt method which is also just a flag to use it for cancellable operations in a thread
Funny, you actually can cancel Thread.sleep
But for all other blocking calls it's usually doesn't work
Also interrupting thread is not want you want on a shared thread pool
r

Rohan Maity

12/18/2018, 1:13 PM
So in this case Thread.sleep is not blocking ?
g

gildor

12/18/2018, 1:15 PM
Is blocking, it's just implemented in a way when it throws InterruptException in case of thread interruption
But Interrupting is probably a bad idea as I said, but also we are not talking probably about thread sleep, it's just an example
v

Vsevolod Tolstopyatov [JB]

12/18/2018, 1:18 PM
Could a cancel request interrupt a running Thread?
No. Interruptions are asynchronous by its nature and can be delivered to the “wrong” coroutine. E.g. what if you run he following
Copy code
val job = launch(singleThreadDispatcher) {
   Thread.sleep(1)
}

val job2 = launch(singleThreadDispatcher) {
  ...
}

job.cancel() // let's assume "cancel" interrupts thread where coroutine is running
How can you guarantee that interrupt will be delivered while
job
is executing, not
job2
?
not talking about the fact, that most of the code does not handle interruptions properly
s

streetsofboston

12/18/2018, 1:19 PM
@gildor Ah, that is what I was seeing, that Thread.sleep is interrupted (not cancelled). This means that a cancellation requests one with a thread-interrupt. Even some socket operations are interruptable. But let's assume, the thread is truly blocking and can't be interrupted. Does
launch
fail to be cancelled because its child-routine in
withContext
is never cancelled?
r

Rohan Maity

12/18/2018, 1:20 PM
Yeah we are not talking about Threads One more thing as Thread.sleep is blocking part . So it keeps running withContext . As withContext is launch it will keep it alive also message is also used in findViewById?
@Vsevolod Tolstopyatov [JB] that was very good example . Thanks for clearing that .
g

gildor

12/18/2018, 1:26 PM
Launch is not failed to be cancelled, it's actually cancelled, but to return launch must wait for child cancellation too
👍 1
s

streetsofboston

12/18/2018, 1:37 PM
Thanks! In short, parent routine's cancellation must wait for all its child-routines' cancellations. Is this correct?
g

gildor

12/18/2018, 3:21 PM
yes
👍 1
9 Views