withTimeoutOrNull returns null even when it did not timeout itself
See original GitHub issueCopied from message by @gregschlom at public slack:
Hey guys. I have an issue with nested withTimeouts. Here’s some example code:
val channel = Channel<Int>()
// this blocks indefinitely if the channel is empty
suspend fun nexValue(): Int {
println("Waiting for next value ")
return channel.receive()
}
// same as nextValue(), but returns null after the timeout expires
suspend fun nextValueWithTimout(t: Long): Int? {
return withTimeoutOrNull(t) { nexValue() }
}
suspend fun longOperation() {
println("Starting long operation")
while (true) {
val v = nextValueWithTimout(1000)
if (v == null) {
println("timed out")
// Nothing was received in our channel.
// Do some other work while we wait for the value to arrive. Maybe we want to re-try sending
// a message to our value producer for example
}
if (v == 42) return
}
}
@Test
fun main() = runBlocking {
// This never returns. Instead we get stuck in an infinite loop in the while() above
withTimeout(5000) {
longOperation()
}
}
The problem here is that we have two nested withTimeout
calls
The code is generally suspended inside nextValue(). When the outer timeout fires (the one in the main function), there’s no way for the code in nextValueWithTimout
to know whether it was it’s own timeout that fired or some other timeout
Therefore it returns null either way
Issue Analytics
- State:
- Created 6 years ago
- Comments:10 (4 by maintainers)
Top Results From Across the Web
How to let withTimeoutOrNull return null but finish code in the ...
I managed to implement something that works but IDE suggest replacing async with withContext(DefaultDispatcher) but it's not working the same.
Read more >withTimeoutOrNull() - Klassbook - CommonsWare
A variant of withTimeout() with withTimeoutOrNull() . This will return either: The result of the lambda expression, if it completes before the timeout....
Read more >Cancellation and timeouts | Kotlin
Run it to see that it continues to print "I'm sleeping" even after cancellation until the job completes by itself after five iterations....
Read more >Kotlin Coroutines - Job and Timeout | by Saurabh Pant
In case a coroutine is computing and not checked for cancellation then ... use the function withTimeoutOrNull which returns null on timeout.
Read more >Why Kotlin Coroutine Withtimeoutornull Takes Longer Than ...
Withtimeoutornull Returns Null Even When It Did Not Timeout Itself Issue 67 Kotlin Kotlinx Coroutines Github source : github.com.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@nkiesel
delay(3)
resume with aCancellationException
withTimeoutOrNull
catches the exception, concludes that it timed out, returns null which gets converted to the string “inner timeout”CancellationException
was swallowed by the innerwithTimeoutOrNull
For the other cases:
test(1, 3, 2)
is identical totest(1, 2, 3)
- outer times out while suspended in thedelay()
test(2, 1, 3)
: inner times out first so you get “inner timeout” as expected (ie: behavior is correct)test(2, 3, 1)
: delay is lower than time outs, so you get the correct behaviortest(3, 1, 2)
: inner times out first, so you get the correct behaviortest(3, 2, 1)
: delay is lower than time outs, so you get the correct behaviorFor reference, the output of the test above is:
Fixed in
develop
branch