Ktor and Kotlin/Native
Tags: kotlin, kotlinmultiplatform, android, ios
Published: 2020-09-01 20:07:01

---
title: Ktor and Kotlin/Native
published: true
description: Ktor and Kotlin/Native had some issues in earlier Kotlin versions. Now some things are fixed, and the situation is much improved, but be aware of some different potential problems.
tags: kotlin, kotlinmultiplatform, android, ios
---

# Ktor and Kotlin/Native

The story of coroutines for Kotlin/Native has been complex for a while now, and with the news that [the Kotlin/Native memory model will be changing](https://blog.jetbrains.com/kotlin/2020/07/kotlin-native-memory-management-roadmap/), coroutines for Kotlin/Native will remain a complex story for some time.

Ktor is built around coroutines. The coroutines situation fundamentally affects how Ktor functions. There have been multiple moving targets in this story, which has created a lot of confusion and a number of bug reports that kind of cross over the same core issues.

In this post, I will attempt to add some clarity to the situation.

## The Coroutines Situation
To be clear, when we're talking about "core
utines", we're generally talking about kotlinx.coroutines. It's technically a separate library, but I can't imagine a realistic situation where you'd actually use coroutines and not include kotlinx.coroutines.

Initially, kotlinx.coroutines for Kotlin/Native was single threaded. You could suspend execution, but not schedule work on different threads. This was due to Kotlin/Native's memory model.

Ktor was designed to run on this single-threaded model. Also, as far as I know on iOS, you would need to initiate Ktor calls from the main thread.

In late 2019, a draft PR emerged which allowed kotlinx.coroutines to communicate across threads. We'll call this the "MT" branch, for "multithreaded". From this branch, there have been parallel library releases. The current main release is '1.3.9' and the current multithreaded release is '1.3.9-native-mt'.

Unless something changes, the parallel branch and release model will likely stay the same for kotlinx.coroutines until the Kotlin/Native memory model update is complete.

## Ktor
Until 1.4, Ktor was still designed to be run with the single-threaded version of kotlinx.coroutines. You *could* run it with the MT version, but you had to be very careful to keep the scope you were in to the main thread and make sure it was never frozen.

It's a little complicated to explain, and not super useful as it's now history, but here it is. Coroutines run in a scope, which has (among other things) a Dispatcher and a Job. When you change the Dispatcher to run code on another thread, that scope gets frozen. Once frozen, everything the Job holds will also be frozen. So, if you were doing something on a background thread in the same scope as something you were doing with Ktor, even if Ktor was only in the main thread, you'd get an InvalidMutabilityException.

I think one of the more confusing parts is that Ktor would work until you involved that scope in a background process, after which it would stop working.

To see this in action, watch the video.

{% youtube vqyv5q5NqVE %}

To get around this, you either need to maintain a different scope for Ktor, and make sure it never got frozen, or isolate the Job. [We did that with KaMPKit](https://github.com/touchlab/KaMPKit/blob/45e20c85b42beea9d2a14ad2819ade135f5b56cd/shared/src/iosMain/kotlin/co/touchlab/kampkit/ktor/Platform.kt). It was a pretty ugly hack, but it worked.

Also, since Ktor depended on the non-MT version, you could unintentionally be using the non-MT version of kotlinx.coroutines even though your dependency configuration explicitly asked for it. You would need to specify that you wanted to use that version.

```kotlin
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9-native-mt") {
    version {
        strictly("1.3.9-native-mt")
    }
}
```

## Kotlin and Ktor 1.4 release

The 1.4 release of Ktor actually fixes this issue. We didn't hear about it for a bit, but I think that was because the issue was confusing to a lot of folks. Although it's fixed for the MT branch, the situation has some further confusion, as the current release of Ktor pulls in the MT branch of kotlinx.coroutines. **If your project expects the single-threaded version of kotlinx.coroutines, this situation can result in some unexpected behavior**.

To experiment with Ktor in the different versions, you can check out our little sample app.

{% github touchlab-lab/ktorcoroutines no-readme %}

The master branch has 1.3.72 and shows the failure that was happening. The kotlin_140 branch has the updated versions and a functional Ktor sample.

## Issues

Ktor needs to be run from the main thread. There are also issues with Ktor and testing, related to the threading restrictions. We'll be digging into this more at some point. Just be aware of it.

Also, Russell tells me there's a [logging issue](https://youtrack.jetbrains.com/issue/KTOR-924) which I'm not even going to dig into right now because I want to publish this today…

# TL;DR

Ktor and kotlinx.coroutines were not working well together on native before 1.4. Now they cooperate better. Using Ktor 1.4 will possibly pull in the MT branch of kotlinx.coroutines, so if your project is not designed for that, be aware that it's possibly an issue.

We've updated KaMP Kit to remove the hack we had put in. Ktor is now just regular Ktor

{% github touchlab/KaMPKit no-readme %}