Peter Samokhin
04/03/2020, 12:31 AM1.3.71
, coroutines: 1.3.5-native-mt
, ktor: 1.3.2
.
Can someone explain to me, how is this working:
For now, this is not possible to do ktor calls in the background.
I know that this is ktor's issue, but only when you are calling HttpClient
from different threads on iOS (according to the github issues), and ktor handles this (does background calls) by itself.
In my case, I do such calls only before, but anyway I got InvalidMutabilityException
.
How this is possible?
A detailed description is below.
I have the code like this:
class IssueReproduce: CoroutineScope {
private val dispatcherUi = // on iOS: Dispatchers.Main
private val dispatcherDefault = // on iOS: Dispatchers.Default
private val job = SupervisorJob()
private val api = SomeApi()
override val coroutineContext = dispatcherUi + job
/* ... */
fun checkAuth() {
launch(coroutineContext) {
// make some call in a background BEFORE
val token = withContext(dispatcherDefault) {
repo.getToken()
}
val response = try {
api.doAuth(token)
} catch (e: Throwable) {
// error:
// kotlin.native.concurrent.InvalidMutabilityException
// mutation attempt of frozen io.ktor.client.request.HttpRequestPipeline@838cd448
}
}
}
}
Where:
class SomeApi {
private val client = HttpClient(/* ... */)
suspend fun doAuth(token: String): SomeDataClass {
return <http://client.post|client.post> {
url(/* ... */)
body = /* ... */
}
}
}
But, when I change code to this:
val token = /* withContext(dispatcherDefault) { */
repo.getToken()
/* } */
i.e. when I make no calls in the background before calling ktor.HttpClient, all is ok and there are no errors.
So, what I'm doing wrong? Removing withContext(dispatcherDefault)
for precending code does the trick, but wrapping ktor calls with withContext(coroutineContext)
or withContext(dispatcherUi)
does not.
How preceding code with the call in the background can affect the thread of the following code?
And how to fix this? As I mentioned above, I tried to wrap ktor calls with the original thread, but it does not help.rudolf.hladik
04/03/2020, 7:21 AMprivate val client by lazy { HttpClient(/* … */)
?Peter Samokhin
04/03/2020, 10:47 AMKris Wong
04/03/2020, 1:08 PMKris Wong
04/03/2020, 1:08 PMKris Wong
04/03/2020, 1:08 PMPeter Samokhin
04/03/2020, 1:26 PMKris Wong
04/03/2020, 1:28 PMKris Wong
04/03/2020, 1:29 PMArkadii Ivanov
04/03/2020, 10:04 PMthis
and freezes the entire class, and so SomeApi
and its HttpClient
. Try moving this call to a separate method and pass repo
as argument.