https://kotlinlang.org logo
#coroutines
Title
# coroutines
n

ntherning

10/20/2020, 6:48 AM
Hi! I'm running into an issue with
Mutex.withLock
and unexpected freezing in my iOS app when upgrading my project to kotlin 1.4.10 and coroutines 1.3.9-native-mt-2. I think I have been able to make a simple reproduction case:
Copy code
runBlocking(newSingleThreadContext("thread")) {
    val mutex = Mutex().apply { ensureNeverFrozen() }
    launch {
        runCatching { mutex.withLock { delay(1000) } }.exceptionOrNull()?.printStackTrace()
    }
    launch {
        runCatching { mutex.withLock { delay(1000) } }.exceptionOrNull()?.printStackTrace()
    }
}
This launches two coroutines in the same worker. Both tries to take the lock and then delays for 1 sec while holding it. As everything happens within the same worker thread I would not expect any mutability issues. But... This is what happens:
Copy code
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlinx.coroutines.sync.MutexImpl.LockedQueue@788375b8
    at kfun:kotlin.Throwable#<init>(kotlin.String?){} + 93 (kotlin/kotlin/Throwable.kt:23:37)
    at kfun:kotlin.Exception#<init>(kotlin.String?){} + 91 (kotlin/kotlin/Exceptions.kt:23:44)
    at kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 91 (kotlin/kotlin/Exceptions.kt:34:44)
    at kfun:kotlin.native.concurrent.InvalidMutabilityException#<init>(kotlin.String){} + 91 (kotlin/kotlin/native/concurrent/Freezing.kt:22:60)
    at ThrowInvalidMutabilityException + 690 (kotlin/kotlin/native/concurrent/Internal.kt:92:11)
    at MutationCheck + 108
    at kfun:kotlinx.coroutines.sync.MutexImpl.LockedQueue.<set-owner>#internal + 102 (sync/Mutex.kt:350:19)
    at kfun:kotlinx.coroutines.sync.MutexImpl#unlock(kotlin.Any?){} + 3740 (sync/Mutex.kt:327:29)
    at kfun:MutexInvalidMutabilityTest.$doTest$lambda-2$lambda-0COROUTINE$0.invokeSuspend#internal + 2206 (MutexInvalidMutabilityTest.kt:16:61)
    ...
You can find the full code and full stack trace it in this gist: https://gist.github.com/ntherning/a1bf85d44a5989d66677762c15587552 Is this expected behavior? Perhaps I am doing something stupid? Or a bug in
MutexImpl
?
t

Tijl

10/20/2020, 6:55 AM
This is know bug fixed in Git already
there is also a suggest workaround there using
Semaphore(1)
, I’d advice using
try/finally
to release the semaphore (or make that into an extension function like withLock)
n

ntherning

10/20/2020, 7:01 AM
Thanks! I will try that workaround.
m

Marc Knaup

10/20/2020, 9:59 AM
@Tijl there is already an extension:
semaphore.withPermit { … }
.
t

Tijl

10/20/2020, 9:59 AM
good point
14 Views