@@ -52,11 +52,38 @@ public inline fun CoroutineExceptionHandler(crossinline handler: (CoroutineConte
52
52
}
53
53
54
54
/* *
55
- * An optional element in the coroutine context to handle uncaught exceptions.
55
+ * An optional element in the coroutine context to handle ** uncaught** exceptions.
56
56
*
57
- * Normally, uncaught exceptions can only result from coroutines created using the [launch][CoroutineScope.launch] builder.
57
+ * Normally, uncaught exceptions can only result from _root_ coroutines created using the [launch][CoroutineScope.launch] builder.
58
+ * All _children_ coroutines (coroutines created in the context of another [Job]) delegate handling of their
59
+ * exceptions to their parent coroutine, which also delegates to the parent, and so on until the root,
60
+ * so the `CoroutineExceptionHandler` installed in their context is never used.
61
+ * Coroutines running with [SupervisorJob] do not propagate exceptions to their parent and are treated like root coroutines.
58
62
* A coroutine that was created using [async][CoroutineScope.async] always catches all its exceptions and represents them
59
- * in the resulting [Deferred] object.
63
+ * in the resulting [Deferred] object, so it cannot result in uncaught exceptions.
64
+ *
65
+ * ### Handling coroutine exceptions
66
+ *
67
+ * `CoroutineExceptionHandler` is a last-resort mechanism for global "catch all" behavior.
68
+ * You cannot recover from the exception in the `CoroutineExceptionHandler`. The coroutine had already completed
69
+ * with the corresponding exception when the handler is called. Normally, the handler is used to
70
+ * log the exception, show some kind of error message, terminate, and/or restart the application.
71
+ *
72
+ * If you need to handle exception in a specific part of the code, it is recommended to use `try`/`catch` around
73
+ * the corresponding code inside your coroutine. This way you can prevent completion of the coroutine
74
+ * with the exception (exception is now _caught_), retry the operation, and/or take other arbitrary actions:
75
+ *
76
+ * ```
77
+ * scope.launch { // launch child coroutine in a scope
78
+ * try {
79
+ * // do something
80
+ * } catch (e: Throwable) {
81
+ * // handle exception
82
+ * }
83
+ * }
84
+ * ```
85
+ *
86
+ * ### Implementation details
60
87
*
61
88
* By default, when no handler is installed, uncaught exception are handled in the following way:
62
89
* * If exception is [CancellationException] then it is ignored
@@ -66,10 +93,7 @@ public inline fun CoroutineExceptionHandler(crossinline handler: (CoroutineConte
66
93
* * Otherwise, all instances of [CoroutineExceptionHandler] found via [ServiceLoader]
67
94
* * and current thread's [Thread.uncaughtExceptionHandler] are invoked.
68
95
*
69
- * [CoroutineExceptionHandler] can be invoked from an arbitrary dispatcher used by coroutines in the current job hierarchy.
70
- * For example, if one has a `MainScope` and launches children of the scope in main and default dispatchers, then exception handler can
71
- * be invoked either in main or in default dispatcher thread regardless of
72
- * which particular dispatcher coroutine that has thrown an exception used.
96
+ * [CoroutineExceptionHandler] can be invoked from an arbitrary thread.
73
97
*/
74
98
public interface CoroutineExceptionHandler : CoroutineContext .Element {
75
99
/* *
0 commit comments