Core. Fix data-race in ApplicationEnvironment initialization

getOrCreateApplicationEnvironment is main entrypoint to create
ApplicationEnvironment in production and compiler tests
It is subject to be called concurrently, that's why
APPLICATION_LOCK exists

ApplicationEnvironment itself hosts Application from idea-core
It is actually singleton, that is subject to be disposed, once all
operations referencing it completes

To properly dispose ApplicationEnvironment when there is no references
left, we maintain reference counter aka ourProjectCount

Originally, there was data-race caused by the fact, that ourProjectCount
was updated after publication of application

Linear, data-race occurs in following order
T1: getOrCreateApplicationEnvironment returns application
T2: Disposes its reference to application, causing ourProjectCount to
reach zero, and disposing application that is already available to T1
T1: Updates counter, but its application already disposed
This commit is contained in:
Simon Ogorodnik
2022-08-12 23:06:54 +02:00
committed by teamcity
parent a6c7d4c0c6
commit f2dee2bf85
2 changed files with 27 additions and 31 deletions
@@ -33,6 +33,17 @@ enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess
DAEMON_RMI_SOCKET_BACKLOG_SIZE_PROPERTY("kotlin.daemon.socket.backlog.size"),
DAEMON_RMI_SOCKET_CONNECT_ATTEMPTS_PROPERTY("kotlin.daemon.socket.connect.attempts"),
DAEMON_RMI_SOCKET_CONNECT_INTERVAL_PROPERTY("kotlin.daemon.socket.connect.interval"),
/**
* Only specify that property if you want to avoid multiple initializations/disposals of KotlinCoreApplicationEnvironment
*
* **If not specified**, KotlinCoreApplicationEnvironment **WILL dispose** after all concurrent compilations finish,
* and will be re-initialized when starting new compilation
*
* If specified, KotlinCoreApplicationEnvironment will **NOT dispose** after all concurrent compilations finished
* and will be pinned with hard-reference
* **THIS LEAKS MEMORY**
* */
KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY("kotlin.environment.keepalive"),
COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS("kotlin.daemon.custom.run.files.path.for.tests"),
COMPILE_INCREMENTAL_WITH_ARTIFACT_TRANSFORM("kotlin.incremental.useClasspathSnapshot"),