question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

withTimeoutOrNull returns null even when it did not timeout itself

See original GitHub issue

Copied 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:closed
  • Created 6 years ago
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
gregschlomcommented, Jun 8, 2017

@nkiesel

Why is nested2(1, 2, 3) not returning “outer timeout”?

  • The outer timeout fires at 1 second, and makes delay(3) resume with a CancellationException
  • The inner withTimeoutOrNull catches the exception, concludes that it timed out, returns null which gets converted to the string “inner timeout”
  • The block in outer timeout completes with a valid value (“inner timeout”), has no idea it actually timed out because the CancellationException was swallowed by the inner withTimeoutOrNull

For the other cases:

  • test(1, 3, 2) is identical to test(1, 2, 3) - outer times out while suspended in the delay()
  • 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 behavior
  • test(3, 1, 2): inner times out first, so you get the correct behavior
  • test(3, 2, 1): delay is lower than time outs, so you get the correct behavior

For reference, the output of the test above is:

test(1, 2, 3) = { 1: inner timeout, 2: inner timeout }
test(1, 3, 2) = { 1: inner timeout, 2: inner timeout }
test(2, 1, 3) = { 1: inner timeout, 2: inner timeout }
test(2, 3, 1) = { 1: delay, 2: delay }
test(3, 1, 2) = { 1: inner timeout, 2: inner timeout }
test(3, 2, 1) = { 1: delay, 2: delay }
0reactions
elizarovcommented, Jun 9, 2017

Fixed in develop branch

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found