Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@jush
Copy link
Contributor

@jush jush commented Mar 21, 2023

Capture any throwable thrown by the generate() function running in a separate thread to later on throw it in the context of the generateDocumentation() calling thread.

Fixes #2934

@IgnatBeresnev IgnatBeresnev self-requested a review March 23, 2023 12:44
Copy link
Contributor

@IgnatBeresnev IgnatBeresnev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, thanks for noticing and fixing it!

Comment on lines 206 to 221
var throwableInGenerate: Throwable? = null
/**
* Run in a new thread to avoid memory leaks that are related to ThreadLocal (that keeps `URLCLassLoader`)
* Currently, all `ThreadLocal`s leaking are in the compiler/IDE codebase.
*/
Thread { generate() }.apply {
Thread {
try {
generate()
} catch (t: Throwable) {
throwableInGenerate = t
}
}.apply {
start()
join()
}
throwableInGenerate?.let { throw it }
Copy link
Contributor

@IgnatBeresnev IgnatBeresnev Apr 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why Kotlin allows writing such code and what exactly happens "under the hood" when this is run on a JVM. Is it thread safe? I can't say for sure...

I do know that you cannot write such code in Java, it requires the used variable to be either final or effectively final for good reasons.

screenshots

2023-04-06_23-11-53
2023-04-06_23-10-50

To be on the safe side, I think we can use AtomicReference to hold the throwable, then it should be thread safe.

While at it, we could use UncaughtExceptionHandler (which actually catches Throwable) instead of the try-catch, but it's optional :)3

To put the words into code:

val uncaughtExceptionHolder = AtomicReference<Throwable?>()
/**
 * Run in a new thread to avoid memory leaks that are related to ThreadLocal (that keeps `URLCLassLoader`)
 * Currently, all `ThreadLocal`s leaking are in the compiler/IDE codebase.
 */
Thread { generate() }.apply {
    setUncaughtExceptionHandler { _, throwable ->
        uncaughtExceptionHolder.set(throwable)
    }
    start()
    join()
}
uncaughtExceptionHolder.get()?.let { throw it }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for looking into it and providing such a detailed guidance.

I'm not sure why Kotlin allows writing such code and what exactly happens "under the hood" when this is run on a JVM. Is it thread safe? I can't say for sure...

I took a look at the bytecode generated (see https://godbolt.org/z/6d47nPs4a) and under the hood is using ObjectRef, which is a static final class that holds an element.
That allows the use of var throwableInGenerate even though it's not really final.

Anyway, that doesn't guarantee thread safety. So your proposed solution using AtomicReference does indeed help with ensuring that the throwable is visible to all threads and it is set atomically.

Copy link
Contributor

@IgnatBeresnev IgnatBeresnev Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, it's nice to know what it's being compiled into, thanks for looking into it and sharing the findings :)

@jush jush force-pushed the jush/fix-build-success-exception branch from 905abc0 to a1f2a2c Compare April 11, 2023 07:20
@jush jush requested a review from IgnatBeresnev April 11, 2023 07:20
Copy link
Contributor

@IgnatBeresnev IgnatBeresnev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thank you very much for the fix, and sorry it took so long to get merged!

@IgnatBeresnev IgnatBeresnev merged commit 115a318 into Kotlin:master Apr 17, 2023
@Kotlin Kotlin deleted a comment from taroenock Apr 21, 2023
@Kotlin Kotlin deleted a comment from taroenock Apr 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gradle build successful even though there are Dokka failures

2 participants