is it possible to put something in a `coroutineCon...
# coroutines
g
is it possible to put something in a
coroutineContext
with a
finalize
that can detect an abandoned coroutine? Maybe print a warning?
e
You can put anything with a finalize in there.
g
How would you detect if the coroutine had been abandoned, ask for the Job's state in a finalize method?
ill play around with it
o
if a coroutine (or the state inside it) finalizes, then it has definitely been abandoned because it is reclaimable by GC (i.e. no references)
g
right now
withContext
is abandoning according to
println
statements I've got, which is wholly unexpected, itl be interesting to see why.
right @octylFractal but its fine if the job compelted normally, what I'm looking for is only the case where the job isnt completed but the GC runs to collect it => somebody is mid-stack and
finally
blocks might not go off.
o
oh, then check
job.isActive
is still
true
👍 1
you may need to pull some trickery to ensure that your state is saved in the coroutine state (wrapping everything with a
finally
block perhaps?), I would inspect the compiled code to ensure it does what you expect
g
well,
Copy code
public class AbandonmentNotifier(val job: Job): AbstractCoroutineContextElement(Key) {

    fun finalize(){
        if(job.isActive){
            println("abandoned!!!")
        }
    }

    private object Key: CoroutineContext.Key<AbandonmentNotifier>
}
does nothing, and my code
Copy code
println("A")
withContext(Dispatchers.Default){
  println("B")
}
prints "A" without printing B
I guess kotlinx-coroutines-debug (https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/debugging.md) is my next step
...and my bug goes away if I run with
-ea
to get that debugging.
🎃 bug.
i guess ill try to get this down to an SSCCE...
e
Debug module tracks each coroutine via a strong reference.
l
Use
yield()
in your tight loops to allow other coroutines to run.
👍 1
e
This might be a bug (starvation) in schedule impl. You can try an updated version from
scheduler-changes
branch
(will be released soon)
g
So, @elizarov this happens without any
Flow
instances stuff, and it only happens when using the intelliJ run button. When using intelliJ's debug or our own installer target its fine. I'm going to start running with
java -jar
invocations by hand to see if I can reproduce the problem. One problem though is that I believe
handleCoroutineException()
is hiding exceptions; I've seen it get hit under the debugger once or twice but no exceptions were printed out. really scary stuff.
e
That is strange. Keep me posted, please, if you find out more
g
Yeah so, if I attach any kind of debugging aide this bug goes away. I also added some output here: https://gist.github.com/Groostav/9f625d2f93e551c36ad26a7be13e0f38
Needless to say if i copy-paste the handler into a unit test everything is fine, so whatever is causing this problem is being resolved somewhere in our own dependent code. I think tomorrow I'll start manually B-searching my own code's dependency graph.
@elizarov Ok so it was just a flooding issue plain and simple. The suprise is that I believe
Dispatchers.Default
was deadlocked, and
<http://Dispatchers.IO|Dispatchers.IO>
appears to use
Dispatchers.Default
for scheduling, so if Default is deadlocked IO is effectively also deadlocked. Could that be considered a bug? Interestingly enough,
jstack
points out the deadlock plain-and-simple, no coroutines involved. I just needed to pay attention to the thread names.