fixup! [Gradle] Use locks to prevent concurrent modification problems in AbstractSetupTask
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt
index cfe724b..883d42a 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt
@@ -20,8 +20,6 @@
 import org.jetbrains.kotlin.gradle.util.replaceText
 import org.jetbrains.kotlin.test.TestMetadata
 import org.junit.jupiter.api.DisplayName
-import org.junit.jupiter.api.parallel.ResourceAccessMode.READ_WRITE
-import org.junit.jupiter.api.parallel.ResourceLock
 import java.io.ObjectInputStream
 import java.nio.file.Files
 import java.nio.file.Path
@@ -105,7 +103,6 @@
     )
     @GradleTest
     @TestMetadata("kotlin-js-plugin-project")
-    @ResourceLock("kgp-js node installation", mode = READ_WRITE)
     fun testBuildMetricsForJsProject(gradleVersion: GradleVersion) {
         testBuildReportInFile(
             "kotlin-js-plugin-project",
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt
index 612b4fe..3bd274e 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt
@@ -17,10 +17,12 @@
 import org.jetbrains.kotlin.gradle.utils.getFile
 import org.jetbrains.kotlin.gradle.utils.mapOrNull
 import java.io.File
+import java.io.RandomAccessFile
 import java.net.URI
-import java.nio.file.Path
 import javax.inject.Inject
-import kotlin.io.path.*
+import kotlin.io.path.createDirectories
+import kotlin.io.path.createFile
+import kotlin.io.path.exists
 
 @DisableCachingByDefault
 abstract class AbstractSetupTask<Env : AbstractEnv, Spec : EnvSpec<Env>>(
@@ -190,8 +192,8 @@
         val currentHash = computeCurrentHash()
 
         val storedHash =
-            if (hashFile.fileSize() > 0) {
-                hashFile.readText().trim()
+            if (hashFile.length() > 0) {
+                hashFile.readLine().trim()
             } else {
                 "<hashFile missing>"
             }
@@ -211,7 +213,7 @@
 
         val updatedHash = computeCurrentHash()
             ?: error("failed to compute hash. destination:$destination, dist:$dist.")
-        hashFile.writeText(updatedHash)
+        hashFile.writeUTF(updatedHash)
     }
 
     private fun computeCurrentHash(): String? {
@@ -250,7 +252,7 @@
      * Concurrent execution happens more often when running KGP integration tests locally,
      * since the tests are run in parallel with multiple Gradle versions.
      */
-    private fun <T> runWithHashFileLock(action: (hashFile: Path) -> T): T {
+    private fun <T> runWithHashFileLock(action: (hashFile: RandomAccessFile) -> T): T {
         val hashFile = destinationHashFileProvider.get().asFile.toPath().apply {
             if (!exists()) {
                 parent.createDirectories()
@@ -258,8 +260,8 @@
             }
         }
 
-        return exclusiveFileLock(hashFile) {
-            action(hashFile)
+        return exclusiveFileLock(hashFile) { lockedFile ->
+            action(lockedFile)
         }
     }
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/exclusiveFileLock.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/exclusiveFileLock.kt
index 9f68df6..e53b536 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/exclusiveFileLock.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/exclusiveFileLock.kt
@@ -6,6 +6,7 @@
 package org.jetbrains.kotlin.gradle.utils
 
 import java.io.RandomAccessFile
+import java.nio.channels.FileChannel
 import java.nio.channels.OverlappingFileLockException
 import java.nio.file.Path
 import java.time.Instant
@@ -36,7 +37,7 @@
 internal fun <T> exclusiveFileLock(
     file: Path,
     lockTimeout: Duration = 5.seconds,
-    block: () -> T,
+    block: (file: RandomAccessFile) -> T,
 ): T {
     contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) }
 
@@ -54,18 +55,12 @@
         do {
             try {
                 RandomAccessFile(file.toFile(), "rw").use { lockFileAccess ->
-                    val fileLock = lockFileAccess.channel.tryLock(
-                        0,
-                        1,
-                        // set shared=false to trigger OverlappingFileLockException
-                        // if the lockfile is used by the same thread
-                        false,
-                    )
+                    val fileLock = lockFileAccess.channel.tryLock()
 
                     if (fileLock != null) {
                         fileLock.use {
                             // Successfully acquired exclusive lock
-                            return block()
+                            return block(lockFileAccess)
                         }
                     } else {
                         // Failed to acquire exclusive lock, already locked by another process