1 /*
<lambda>null2 * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3 */
4
5 // Need InlineOnly for efficient bytecode on Android
6 @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
7
8 package kotlinx.coroutines
9
10 import kotlinx.coroutines.internal.*
11 import java.util.concurrent.atomic.*
12 import kotlin.internal.InlineOnly
13
14 /**
15 * Name of the property that controls coroutine debugging.
16 *
17 * ### Debugging facilities
18 *
19 * In debug mode every coroutine is assigned a unique consecutive identifier.
20 * Every thread that executes a coroutine has its name modified to include the name and identifier of
21 * the currently running coroutine.
22 *
23 * Enable debugging facilities with "`kotlinx.coroutines.debug`" ([DEBUG_PROPERTY_NAME]) system property,
24 * use the following values:
25 *
26 * * "`auto`" (default mode, [DEBUG_PROPERTY_VALUE_AUTO]) -- enabled when assertions are enabled with "`-ea`" JVM option.
27 * * "`on`" ([DEBUG_PROPERTY_VALUE_ON]) or empty string -- enabled.
28 * * "`off`" ([DEBUG_PROPERTY_VALUE_OFF]) -- disabled.
29 *
30 * Coroutine name can be explicitly assigned using [CoroutineName] context element.
31 * The string "coroutine" is used as a default name.
32 *
33 * Debugging facilities are implemented by [newCoroutineContext][CoroutineScope.newCoroutineContext] function that
34 * is used in all coroutine builders to create context of a new coroutine.
35 */
36 public const val DEBUG_PROPERTY_NAME: String = "kotlinx.coroutines.debug"
37
38 /**
39 * Name of the boolean property that controls stacktrace recovery (enabled by default) on JVM.
40 * Stacktrace recovery is enabled if both debug and stacktrace recovery modes are enabled.
41 *
42 * Stacktrace recovery mode wraps every exception into the exception of the same type with original exception
43 * as cause, but with stacktrace of the current coroutine.
44 * Exception is instantiated using reflection by using no-arg, cause or cause and message constructor.
45 *
46 * This mechanism is currently supported for channels, [async], [launch], [coroutineScope], [supervisorScope]
47 * and [withContext] builders.
48 */
49 internal const val STACKTRACE_RECOVERY_PROPERTY_NAME = "kotlinx.coroutines.stacktrace.recovery"
50
51 /**
52 * Automatic debug configuration value for [DEBUG_PROPERTY_NAME].
53 */
54 public const val DEBUG_PROPERTY_VALUE_AUTO: String = "auto"
55
56 /**
57 * Debug turned on value for [DEBUG_PROPERTY_NAME].
58 */
59 public const val DEBUG_PROPERTY_VALUE_ON: String = "on"
60
61 /**
62 * Debug turned off value for [DEBUG_PROPERTY_NAME].
63 */
64 public const val DEBUG_PROPERTY_VALUE_OFF: String = "off"
65
66 // @JvmField: Don't use JvmField here to enable R8 optimizations via "assumenosideeffects"
67 internal val ASSERTIONS_ENABLED = CoroutineId::class.java.desiredAssertionStatus()
68
69 // @JvmField: Don't use JvmField here to enable R8 optimizations via "assumenosideeffects"
70 internal actual val DEBUG = systemProp(DEBUG_PROPERTY_NAME).let { value ->
71 when (value) {
72 DEBUG_PROPERTY_VALUE_AUTO, null -> ASSERTIONS_ENABLED
73 DEBUG_PROPERTY_VALUE_ON, "" -> true
74 DEBUG_PROPERTY_VALUE_OFF -> false
75 else -> error("System property '$DEBUG_PROPERTY_NAME' has unrecognized value '$value'")
76 }
77 }
78
79 // Note: stack-trace recovery is enabled only in debug mode
80 // @JvmField: Don't use JvmField here to enable R8 optimizations via "assumenosideeffects"
81 internal actual val RECOVER_STACK_TRACES =
82 DEBUG && systemProp(STACKTRACE_RECOVERY_PROPERTY_NAME, true)
83
84 // It is used only in debug mode
85 internal val COROUTINE_ID = AtomicLong(0)
86
87 // for tests only
resetCoroutineIdnull88 internal fun resetCoroutineId() {
89 COROUTINE_ID.set(0)
90 }
91
92 @InlineOnly
assertnull93 internal actual inline fun assert(value: () -> Boolean) {
94 if (ASSERTIONS_ENABLED && !value()) throw AssertionError()
95 }
96