blob: 178f528ae219a0dffbdc612af91ef419251530b2 [file] [log] [blame] [view]
hadihariri7db55532018-09-15 10:35:08 +02001<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
2/*
Roman Elizarovdb0ef0c2019-07-03 15:02:44 +03003 * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
hadihariri7db55532018-09-15 10:35:08 +02004 */
5
6// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarov0950dfa2018-07-13 10:33:25 +03007package kotlinx.coroutines.guide.$$1$$2
hadihariri7db55532018-09-15 10:35:08 +02008-->
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +03009<!--- KNIT ../kotlinx-coroutines-core/jvm/test/guide/.*\.kt -->
10<!--- TEST_OUT ../kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt
hadihariri7db55532018-09-15 10:35:08 +020011// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarov0950dfa2018-07-13 10:33:25 +030012package kotlinx.coroutines.guide.test
hadihariri7db55532018-09-15 10:35:08 +020013
14import org.junit.Test
15
16class ExceptionsGuideTest {
17-->
Prendotab8a559d2018-11-30 16:24:23 +030018**Table of contents**
hadihariri7db55532018-09-15 10:35:08 +020019
20<!--- TOC -->
21
Roman Elizarov3258e1f2019-08-22 20:08:48 +030022* [Exception Handling](#exception-handling)
hadihariri7db55532018-09-15 10:35:08 +020023 * [Exception propagation](#exception-propagation)
24 * [CoroutineExceptionHandler](#coroutineexceptionhandler)
25 * [Cancellation and exceptions](#cancellation-and-exceptions)
26 * [Exceptions aggregation](#exceptions-aggregation)
Roman Elizarov3258e1f2019-08-22 20:08:48 +030027 * [Supervision](#supervision)
28 * [Supervision job](#supervision-job)
29 * [Supervision scope](#supervision-scope)
30 * [Exceptions in supervised coroutines](#exceptions-in-supervised-coroutines)
hadihariri7db55532018-09-15 10:35:08 +020031
32<!--- END_TOC -->
33
Roman Elizarov3258e1f2019-08-22 20:08:48 +030034## Exception Handling
hadihariri7db55532018-09-15 10:35:08 +020035
hadihariri7db55532018-09-15 10:35:08 +020036
37This section covers exception handling and cancellation on exceptions.
38We already know that cancelled coroutine throws [CancellationException] in suspension points and that it
39is ignored by coroutines machinery. But what happens if an exception is thrown during cancellation or multiple children of the same
40coroutine throw an exception?
41
42### Exception propagation
43
44Coroutine builders come in two flavors: propagating exceptions automatically ([launch] and [actor]) or
45exposing them to users ([async] and [produce]).
Kenji Otsuka4c76c6f2018-10-12 07:27:08 +090046The former treat exceptions as unhandled, similar to Java's `Thread.uncaughtExceptionHandler`,
hadihariri7db55532018-09-15 10:35:08 +020047while the latter are relying on the user to consume the final
48exception, for example via [await][Deferred.await] or [receive][ReceiveChannel.receive]
Alexander Prendotacbeef102018-09-27 18:42:04 +030049([produce] and [receive][ReceiveChannel.receive] are covered later in [Channels](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/channels.md) section).
hadihariri7db55532018-09-15 10:35:08 +020050
Inego6da0ccd2019-04-21 14:26:40 +070051It can be demonstrated by a simple example that creates coroutines in the [GlobalScope]:
hadihariri7db55532018-09-15 10:35:08 +020052
Alexander Prendotacbeef102018-09-27 18:42:04 +030053<div class="sample" markdown="1" theme="idea" data-highlight-only>
54
hadihariri7db55532018-09-15 10:35:08 +020055```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +030056import kotlinx.coroutines.*
57
58fun main() = runBlocking {
hadihariri7db55532018-09-15 10:35:08 +020059 val job = GlobalScope.launch {
60 println("Throwing exception from launch")
61 throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
62 }
63 job.join()
64 println("Joined failed job")
65 val deferred = GlobalScope.async {
66 println("Throwing exception from async")
67 throw ArithmeticException() // Nothing is printed, relying on user to call await
68 }
69 try {
70 deferred.await()
71 println("Unreached")
72 } catch (e: ArithmeticException) {
73 println("Caught ArithmeticException")
74 }
75}
76```
77
Alexander Prendotacbeef102018-09-27 18:42:04 +030078</div>
79
Inego69c26df2019-04-21 14:51:25 +070080> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt).
hadihariri7db55532018-09-15 10:35:08 +020081
Alexander Prendotacbeef102018-09-27 18:42:04 +030082The output of this code is (with [debug](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/coroutine-context-and-dispatchers.md#debugging-coroutines-and-threads)):
hadihariri7db55532018-09-15 10:35:08 +020083
84```text
85Throwing exception from launch
Roman Elizarov303708b2018-09-28 12:20:49 +030086Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
hadihariri7db55532018-09-15 10:35:08 +020087Joined failed job
88Throwing exception from async
89Caught ArithmeticException
90```
91
92<!--- TEST EXCEPTION-->
93
94### CoroutineExceptionHandler
95
96But what if one does not want to print all exceptions to the console?
97[CoroutineExceptionHandler] context element is used as generic `catch` block of coroutine where custom logging or exception handling may take place.
98It is similar to using [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
99
100On JVM it is possible to redefine global exception handler for all coroutines by registering [CoroutineExceptionHandler] via
101[`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
102Global exception handler is similar to
103[`Thread.defaultUncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler))
104which is used when no more specific handlers are registered.
105On Android, `uncaughtExceptionPreHandler` is installed as a global coroutine exception handler.
106
107[CoroutineExceptionHandler] is invoked only on exceptions which are not expected to be handled by the user,
108so registering it in [async] builder and the like of it has no effect.
109
Prendota65e6c8c2018-10-17 11:51:08 +0300110<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300111
hadihariri7db55532018-09-15 10:35:08 +0200112```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300113import kotlinx.coroutines.*
114
115fun main() = runBlocking {
116//sampleStart
hadihariri7db55532018-09-15 10:35:08 +0200117 val handler = CoroutineExceptionHandler { _, exception ->
118 println("Caught $exception")
119 }
120 val job = GlobalScope.launch(handler) {
121 throw AssertionError()
122 }
123 val deferred = GlobalScope.async(handler) {
124 throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
125 }
126 joinAll(job, deferred)
Prendota65e6c8c2018-10-17 11:51:08 +0300127//sampleEnd
hadihariri7db55532018-09-15 10:35:08 +0200128}
129```
130
Alexander Prendotacbeef102018-09-27 18:42:04 +0300131</div>
132
Inego69c26df2019-04-21 14:51:25 +0700133> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt).
hadihariri7db55532018-09-15 10:35:08 +0200134
135The output of this code is:
136
137```text
138Caught java.lang.AssertionError
139```
140
141<!--- TEST-->
142
143### Cancellation and exceptions
144
145Cancellation is tightly bound with exceptions. Coroutines internally use `CancellationException` for cancellation, these
146exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can
147be obtained by `catch` block.
Marek Langiewiczb6dd65c2019-10-18 12:10:27 +0200148When a coroutine is cancelled using [Job.cancel], it terminates, but it does not cancel its parent.
hadihariri7db55532018-09-15 10:35:08 +0200149
Prendota65e6c8c2018-10-17 11:51:08 +0300150<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300151
hadihariri7db55532018-09-15 10:35:08 +0200152```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300153import kotlinx.coroutines.*
154
155fun main() = runBlocking {
156//sampleStart
hadihariri7db55532018-09-15 10:35:08 +0200157 val job = launch {
158 val child = launch {
159 try {
160 delay(Long.MAX_VALUE)
161 } finally {
162 println("Child is cancelled")
163 }
164 }
165 yield()
166 println("Cancelling child")
167 child.cancel()
168 child.join()
169 yield()
170 println("Parent is not cancelled")
171 }
172 job.join()
Prendota65e6c8c2018-10-17 11:51:08 +0300173//sampleEnd
hadihariri7db55532018-09-15 10:35:08 +0200174}
175```
176
Alexander Prendotacbeef102018-09-27 18:42:04 +0300177</div>
178
Inego69c26df2019-04-21 14:51:25 +0700179> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt).
hadihariri7db55532018-09-15 10:35:08 +0200180
181The output of this code is:
182
183```text
184Cancelling child
185Child is cancelled
186Parent is not cancelled
187```
188
189<!--- TEST-->
190
andrethielef605b262019-10-03 12:18:37 +0200191If a coroutine encounters an exception other than `CancellationException`, it cancels its parent with that exception.
hadihariri7db55532018-09-15 10:35:08 +0200192This behaviour cannot be overridden and is used to provide stable coroutines hierarchies for
Alexander Prendotacbeef102018-09-27 18:42:04 +0300193[structured concurrency](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/composing-suspending-functions.md#structured-concurrency-with-async) which do not depend on
hadihariri7db55532018-09-15 10:35:08 +0200194[CoroutineExceptionHandler] implementation.
195The original exception is handled by the parent when all its children terminate.
196
197> This also a reason why, in these examples, [CoroutineExceptionHandler] is always installed to a coroutine
198that is created in [GlobalScope]. It does not make sense to install an exception handler to a coroutine that
199is launched in the scope of the main [runBlocking], since the main coroutine is going to be always cancelled
200when its child completes with exception despite the installed handler.
201
Prendota65e6c8c2018-10-17 11:51:08 +0300202<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300203
hadihariri7db55532018-09-15 10:35:08 +0200204```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300205import kotlinx.coroutines.*
206
207fun main() = runBlocking {
巳月55a48fb2018-10-31 18:27:47 +0800208//sampleStart
hadihariri7db55532018-09-15 10:35:08 +0200209 val handler = CoroutineExceptionHandler { _, exception ->
210 println("Caught $exception")
211 }
212 val job = GlobalScope.launch(handler) {
213 launch { // the first child
214 try {
215 delay(Long.MAX_VALUE)
216 } finally {
217 withContext(NonCancellable) {
218 println("Children are cancelled, but exception is not handled until all children terminate")
219 delay(100)
220 println("The first child finished its non cancellable block")
221 }
222 }
223 }
224 launch { // the second child
225 delay(10)
226 println("Second child throws an exception")
227 throw ArithmeticException()
228 }
229 }
230 job.join()
Prendota65e6c8c2018-10-17 11:51:08 +0300231//sampleEnd
hadihariri7db55532018-09-15 10:35:08 +0200232}
233```
234
Alexander Prendotacbeef102018-09-27 18:42:04 +0300235</div>
236
Inego69c26df2019-04-21 14:51:25 +0700237> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt).
hadihariri7db55532018-09-15 10:35:08 +0200238
239The output of this code is:
240
241```text
242Second child throws an exception
243Children are cancelled, but exception is not handled until all children terminate
244The first child finished its non cancellable block
245Caught java.lang.ArithmeticException
246```
247<!--- TEST-->
248
249### Exceptions aggregation
250
251What happens if multiple children of a coroutine throw an exception?
252The general rule is "the first exception wins", so the first thrown exception is exposed to the handler.
253But that may cause lost exceptions, for example if coroutine throws an exception in its `finally` block.
254So, additional exceptions are suppressed.
255
256> One of the solutions would have been to report each exception separately,
257but then [Deferred.await] should have had the same mechanism to avoid behavioural inconsistency and this
Andrii Chubko57680672018-10-17 03:56:57 +0300258would cause implementation details of a coroutines (whether it had delegated parts of its work to its children or not)
hadihariri7db55532018-09-15 10:35:08 +0200259to leak to its exception handler.
260
Prendota65e6c8c2018-10-17 11:51:08 +0300261
hadihariri7db55532018-09-15 10:35:08 +0200262<!--- INCLUDE
Prendota65e6c8c2018-10-17 11:51:08 +0300263
Roman Elizarov0950dfa2018-07-13 10:33:25 +0300264import kotlinx.coroutines.exceptions.*
hadihariri7db55532018-09-15 10:35:08 +0200265-->
266
Prendota65e6c8c2018-10-17 11:51:08 +0300267<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300268
hadihariri7db55532018-09-15 10:35:08 +0200269```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300270import kotlinx.coroutines.*
271import java.io.*
272
273fun main() = runBlocking {
hadihariri7db55532018-09-15 10:35:08 +0200274 val handler = CoroutineExceptionHandler { _, exception ->
Roman Elizarov54617b72018-09-28 17:42:44 +0300275 println("Caught $exception with suppressed ${exception.suppressed.contentToString()}")
hadihariri7db55532018-09-15 10:35:08 +0200276 }
277 val job = GlobalScope.launch(handler) {
278 launch {
279 try {
280 delay(Long.MAX_VALUE)
281 } finally {
282 throw ArithmeticException()
283 }
284 }
285 launch {
Roman Elizarov938c5e92018-09-28 16:10:09 +0300286 delay(100)
hadihariri7db55532018-09-15 10:35:08 +0200287 throw IOException()
288 }
289 delay(Long.MAX_VALUE)
290 }
Prendota65e6c8c2018-10-17 11:51:08 +0300291 job.join()
hadihariri7db55532018-09-15 10:35:08 +0200292}
293```
294
Alexander Prendotacbeef102018-09-27 18:42:04 +0300295</div>
296
Inego69c26df2019-04-21 14:51:25 +0700297> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt).
hadihariri7db55532018-09-15 10:35:08 +0200298
Roman Elizarov54617b72018-09-28 17:42:44 +0300299> Note: This above code will work properly only on JDK7+ that supports `suppressed` exceptions
300
hadihariri7db55532018-09-15 10:35:08 +0200301The output of this code is:
302
303```text
304Caught java.io.IOException with suppressed [java.lang.ArithmeticException]
305```
306
307<!--- TEST-->
308
309> Note, this mechanism currently works only on Java version 1.7+.
310Limitation on JS and Native is temporary and will be fixed in the future.
311
312Cancellation exceptions are transparent and unwrapped by default:
313
Prendota65e6c8c2018-10-17 11:51:08 +0300314<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300315
hadihariri7db55532018-09-15 10:35:08 +0200316```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300317import kotlinx.coroutines.*
318import java.io.*
319
320fun main() = runBlocking {
321//sampleStart
hadihariri7db55532018-09-15 10:35:08 +0200322 val handler = CoroutineExceptionHandler { _, exception ->
323 println("Caught original $exception")
324 }
325 val job = GlobalScope.launch(handler) {
326 val inner = launch {
327 launch {
328 launch {
329 throw IOException()
330 }
331 }
332 }
333 try {
334 inner.join()
Vsevolod Tolstopyatova2d80882018-09-24 19:51:49 +0300335 } catch (e: CancellationException) {
336 println("Rethrowing CancellationException with original cause")
hadihariri7db55532018-09-15 10:35:08 +0200337 throw e
338 }
339 }
340 job.join()
Prendota65e6c8c2018-10-17 11:51:08 +0300341//sampleEnd
hadihariri7db55532018-09-15 10:35:08 +0200342}
343```
344
Alexander Prendotacbeef102018-09-27 18:42:04 +0300345</div>
346
Inego69c26df2019-04-21 14:51:25 +0700347> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt).
hadihariri7db55532018-09-15 10:35:08 +0200348
349The output of this code is:
350
351```text
Vsevolod Tolstopyatova2d80882018-09-24 19:51:49 +0300352Rethrowing CancellationException with original cause
hadihariri7db55532018-09-15 10:35:08 +0200353Caught original java.io.IOException
354```
355<!--- TEST-->
Roman Elizarov99c28aa2018-09-23 18:42:36 +0300356
Roman Elizarov3258e1f2019-08-22 20:08:48 +0300357### Supervision
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300358
359As we have studied before, cancellation is a bidirectional relationship propagating through the whole
360coroutines hierarchy. But what if unidirectional cancellation is required?
361
Aaron Stacy2fe443b2019-03-24 20:00:36 -0500362A good example of such a requirement is a UI component with the job defined in its scope. If any of the UI's child tasks
363have failed, it is not always necessary to cancel (effectively kill) the whole UI component,
364but if UI component is destroyed (and its job is cancelled), then it is necessary to fail all child jobs as their results are no longer required.
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300365
366Another example is a server process that spawns several children jobs and needs to _supervise_
367their execution, tracking their failures and restarting just those children jobs that had failed.
368
Roman Elizarov3258e1f2019-08-22 20:08:48 +0300369#### Supervision job
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300370
371For these purposes [SupervisorJob][SupervisorJob()] can be used. It is similar to a regular [Job][Job()] with the only exception that cancellation is propagated
372only downwards. It is easy to demonstrate with an example:
373
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300374<div class="sample" markdown="1" theme="idea" data-highlight-only>
375
376```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300377import kotlinx.coroutines.*
378
379fun main() = runBlocking {
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300380 val supervisor = SupervisorJob()
381 with(CoroutineScope(coroutineContext + supervisor)) {
Vadym Od9819662018-10-19 16:16:57 -0500382 // launch the first child -- its exception is ignored for this example (don't do this in practice!)
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300383 val firstChild = launch(CoroutineExceptionHandler { _, _ -> }) {
384 println("First child is failing")
385 throw AssertionError("First child is cancelled")
386 }
387 // launch the second child
388 val secondChild = launch {
389 firstChild.join()
390 // Cancellation of the first child is not propagated to the second child
391 println("First child is cancelled: ${firstChild.isCancelled}, but second one is still active")
392 try {
393 delay(Long.MAX_VALUE)
394 } finally {
395 // But cancellation of the supervisor is propagated
396 println("Second child is cancelled because supervisor is cancelled")
397 }
398 }
399 // wait until the first child fails & completes
400 firstChild.join()
401 println("Cancelling supervisor")
402 supervisor.cancel()
403 secondChild.join()
404 }
405}
406```
407
408</div>
409
Inego69c26df2019-04-21 14:51:25 +0700410> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt).
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300411
412The output of this code is:
413
414```text
415First child is failing
416First child is cancelled: true, but second one is still active
417Cancelling supervisor
418Second child is cancelled because supervisor is cancelled
419```
420<!--- TEST-->
421
422
Roman Elizarov3258e1f2019-08-22 20:08:48 +0300423#### Supervision scope
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300424
425For *scoped* concurrency [supervisorScope] can be used instead of [coroutineScope] for the same purpose. It propagates cancellation
426only in one direction and cancels all children only if it has failed itself. It also waits for all children before completion
427just like [coroutineScope] does.
428
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300429<div class="sample" markdown="1" theme="idea" data-highlight-only>
430
431```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300432import kotlin.coroutines.*
433import kotlinx.coroutines.*
434
435fun main() = runBlocking {
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300436 try {
437 supervisorScope {
438 val child = launch {
439 try {
440 println("Child is sleeping")
441 delay(Long.MAX_VALUE)
442 } finally {
443 println("Child is cancelled")
444 }
445 }
446 // Give our child a chance to execute and print using yield
447 yield()
448 println("Throwing exception from scope")
449 throw AssertionError()
450 }
451 } catch(e: AssertionError) {
452 println("Caught assertion error")
453 }
454}
455```
456
457</div>
458
Inego69c26df2019-04-21 14:51:25 +0700459> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt).
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300460
461The output of this code is:
462
463```text
464Child is sleeping
465Throwing exception from scope
466Child is cancelled
467Caught assertion error
468```
469<!--- TEST-->
470
Roman Elizarov3258e1f2019-08-22 20:08:48 +0300471#### Exceptions in supervised coroutines
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300472
473Another crucial difference between regular and supervisor jobs is exception handling.
474Every child should handle its exceptions by itself via exception handling mechanisms.
475This difference comes from the fact that child's failure is not propagated to the parent.
476
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300477<div class="sample" markdown="1" theme="idea" data-highlight-only>
478
479```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300480import kotlin.coroutines.*
481import kotlinx.coroutines.*
482
483fun main() = runBlocking {
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300484 val handler = CoroutineExceptionHandler { _, exception ->
485 println("Caught $exception")
486 }
487 supervisorScope {
488 val child = launch(handler) {
489 println("Child throws an exception")
490 throw AssertionError()
491 }
492 println("Scope is completing")
493 }
494 println("Scope is completed")
495}
496```
497
498</div>
499
Inego69c26df2019-04-21 14:51:25 +0700500> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt).
Vsevolod Tolstopyatov49f25a52018-09-28 13:34:10 +0300501
502The output of this code is:
503
504```text
505Scope is completing
506Child throws an exception
507Caught java.lang.AssertionError
508Scope is completed
509```
510<!--- TEST-->
511
Roman Elizarov99c28aa2018-09-23 18:42:36 +0300512<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarov0950dfa2018-07-13 10:33:25 +0300513<!--- INDEX kotlinx.coroutines -->
514[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
515[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
516[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
517[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html
518[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
519[CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/index.html
520[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
521[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
522[SupervisorJob()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-supervisor-job.html
523[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job.html
524[supervisorScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/supervisor-scope.html
525[coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
526<!--- INDEX kotlinx.coroutines.channels -->
527[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
528[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
529[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
Roman Elizarov99c28aa2018-09-23 18:42:36 +0300530<!--- END -->