@@ -72,7 +72,7 @@ internal fun scheduledExecutorShutdownNowAndRelease() {
7272 * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
7373 * cancellable suspending function inside the block throws [CancellationException], so normally that exception,
7474 * if uncaught, also gets thrown by `withTimeout` as a result.
75- * However, the code in the block can suppresses [CancellationException].
75+ * However, the code in the block can suppress [CancellationException].
7676 *
7777 * The sibling function that does not throw exception on timeout is [withTimeoutOrNull].
7878 * Note, that timeout action can be specified for [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause.
@@ -107,19 +107,19 @@ private class TimeoutExceptionCoroutine<in T>(
107107 private val cont : Continuation <T >
108108) : JobSupport(active = true ), Runnable, Continuation<T> {
109109 override val context: CoroutineContext = cont.context + this // mix in this Job into the context
110- override fun run () { cancel(TimeoutException (time, unit)) }
110+ override fun run () { cancel(TimeoutException (time, unit, this )) }
111111 override fun resume (value : T ) { cont.resumeDirect(value) }
112112 override fun resumeWithException (exception : Throwable ) { cont.resumeDirectWithException(exception) }
113113}
114114
115115/* *
116116 * Runs a given suspending block of code inside a coroutine with a specified timeout and returns
117- * `null` if timeout was exceeded.
117+ * `null` if this timeout was exceeded.
118118 *
119119 * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
120120 * cancellable suspending function inside the block throws [CancellationException]. Normally that exception,
121121 * if uncaught by the block, gets converted into the `null` result of `withTimeoutOrNull`.
122- * However, the code in the block can suppresses [CancellationException].
122+ * However, the code in the block can suppress [CancellationException].
123123 *
124124 * The sibling function that throws exception on timeout is [withTimeout].
125125 * Note, that timeout action can be specified for [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause.
@@ -158,14 +158,18 @@ private class TimeoutNullCoroutine<in T>(
158158 private val cont : Continuation <T ?>
159159) : JobSupport(active = true ), Runnable, Continuation<T> {
160160 override val context: CoroutineContext = cont.context + this // mix in this Job into the context
161- override fun run () { cancel(TimeoutException (time, unit)) }
161+ override fun run () { cancel(TimeoutException (time, unit, this )) }
162162 override fun resume (value : T ) { cont.resumeDirect(value) }
163163 override fun resumeWithException (exception : Throwable ) {
164164 // suppress inner timeout exception and replace it with null
165- if (exception is TimeoutException )
165+ if (exception is TimeoutException && exception.coroutine == = this )
166166 cont.resumeDirect(null ) else
167167 cont.resumeDirectWithException(exception)
168168 }
169169}
170170
171- private class TimeoutException (time : Long , unit : TimeUnit ) : CancellationException(" Timed out waiting for $time $unit " )
171+ private class TimeoutException (
172+ time : Long ,
173+ unit : TimeUnit ,
174+ @JvmField val coroutine : Job
175+ ) : CancellationException(" Timed out waiting for $time $unit " )
0 commit comments