Kotlin coroutines: Report usage of runBlocking

kotlin

(Jonathan Cornaz) #1

Description

When one start to use Kotlin Coroutines it may sometime be tempting to use runBlocking.

But in produciton it is generally a bad idea.

First of all it blocks a thread, which waste resources.

And it can also create a deadlock when called from a single-threaded context and one suspend until something is done that context. Here’s an example using JavaFx:

@FXML
fun handleAction() { // <-- Invoked by the JavaFx platform on the JavaFx platform thread
	runBlocking { // <-- Blocks the JavaFx platform thread
	
		// The following, schedule a job on the JavaFx platform thread and suspend until it has been executed.
		// but since the thread is currently blocked it will never be executed, and thus create a deadlock freezing the UI.
		withContext(Dispatchers.JavaFx) {	
			pritnln("hello from UI thread")
		} 
	}
}

Snippet of non-compliant code

fun usage() {
	runBlocking {
		delay(1000)
	}
}

Snippet of compliant code (fixing the above noncompliant code)

suspend fun usage() {
	delay(1000)
}

or

fun usage() {
	GlobalScope.launch { delay(1000) }
}

External references

The documentation of runBlocking itself states:

This function should not be used from coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.

The kotlin team working on coroutines even wanted to make runBlocking fail fast when invoked from some UI threads: https://github.com/Kotlin/kotlinx.coroutines/issues/227.

Type : Bug

May slow down the application or worse: cause deadlocks.

I would personally set the default severity to “Critical”

Tags

performance, multi-threading, pitfall

Scope: Production

runBlocking is legit and needed in tests.