CLOVIS
09/04/2026, 1:43 PMDmitry Khalanskiy [JB]
09/04/2026, 1:59 PMkotlinx.coroutines from the inside, not as part of an application, so I'm not sure how applicable this advice is.
If the program is a black box (i.e., you can't inject your callbacks to arbitrary places), you'll have to write concurrent stress tests. Start two threads in parallel, one cancelling the program at a random point in time, the other running the program. Repeat 10000 times.
If you can inject actions to specific points, then what you want is probably a "latch" (docs.oracle.com/javase/…/CountDownLatch.html) or a "barrier" (docs.oracle.com/javase/…/CyclicBarrier.html). The suspend version of a latch is fun Job(): CompletableJob with its CompletableJob.complete() and Job.join() methods. Barriers are trickier, but also more rarely needed. With a latch, you can wait until right before the suspension, then trigger the cancellation and observe the result.
Please feel free to share specific code snippets, so that we could brainstorm ways to test them.CLOVIS
09/04/2026, 2:06 PMCLOVIS
09/04/2026, 2:08 PMrequest.output (which is a CompletableDeferred) is cancelled, because that means the consumer isn't listening for the results anymore
The red lines are the positions where I think it's interesting to know how the code behaves on cancellationsimon.vergauwen
09/04/2026, 2:26 PMCLOVIS
09/04/2026, 2:27 PMCLOVIS
09/04/2026, 2:29 PMsimon.vergauwen
09/04/2026, 2:30 PMCompletableDeferred<Unit>() as latch or CompletableDeferred<Throwable?>() to inspect exit state of an operation where null is success here.CLOVIS
09/04/2026, 2:30 PMsimon.vergauwen
09/04/2026, 2:31 PMCLOVIS
09/04/2026, 2:32 PMCLOVIS
09/04/2026, 2:34 PMCLOVIS
09/04/2026, 2:35 PMCLOVIS
09/04/2026, 2:35 PMOliver.O
09/04/2026, 3:12 PMGate to reliably provoke potentially conflicting scenarios: github.com/OliverO2/kmp-e2e-stress-testing-example/blob/…/Gate.kt
I accept that you're wary of polluting production code, but maybe you can find a less intrusive solution which might be acceptable.Wout Werkman
09/05/2026, 3:54 PMyield() before both your isActive
checks.
github.com/brokenhappy/KotlinMultiplatformWorkshopWarsaw2024/blob/…/RandomizedDispatchOrder.kt#…
While there are many concurrency bugs it won't catch. It could get much better coverage across suspension point interleavings.
And it has found many bugs in my project.
I've been talking about it with some people in the field to discuss whether it's worth exploring this idea. The cool thing is that this doesn't need instrumentation, and it can be done per coroutine tree.
You can build very domain specific interleaving tests in coroutines because you have access to dispatchers, which is pretty cool.