Skip to content

[Bug] backgroundScope coroutines can trigger UncaughtExceptionsBeforeTest #4685

Description

@viluon

What is happening? What should have happened instead?

Currently, the backgroundScope in a runTest block is cancelled, but may leave coroutines running.

I believe its job should be .join()ed as well. Otherwise, subsequent tests can throw kotlinx.coroutines.test.UncaughtExceptionsBeforeTest.

Reproducer

See https://pl.kotl.in/okOqxIhaC

import kotlinx.coroutines.*
import kotlinx.coroutines.test.*

fun main() {
   runTest {
       backgroundScope.launch(Dispatchers.Default) {
           withContext(NonCancellable) {
               delay(1_000)
               error("hmm")
           }
       }

       delay(50)
   }

   Thread.sleep(1_500)

   runTest {
       println("I'm innocent")
   }
}

Code like this can occasionally crash with kotlinx.coroutines.test.UncaughtExceptionsBeforeTest, although I haven't been able to reproduce it in the playground.

Anything else? (optional)

I originally ran into this with a Ktor server launched in the backgroundScope when running tests in-process via the Mill build system, using isolated classloaders for the tests themselves but a shared classloader for ~clean dependencies, including kotlinx-coroutines-test. This led to a race between the Ktor server shutting down and Mill unloading the isolated classloader for the given test. When Mill was faster, the leftover coroutines in backgroundScope started running into NoClassDefFoundErrors, in turn triggering UncaughtExceptionsBeforeTest with the next runTest invocation, whatever that may have been.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions