Skip to content

Commit 6b98863

Browse files
authored
[Android] [bdUpload] Fix java.nio.channels.OverlappingFileLockException (#881)
1 parent 898cec1 commit 6b98863

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
**Added**
2323

24-
- Nothing yet!
24+
- io.bitdrift.capture-plugin: Fix concurrent `bdUpload` task execution with certain CI scenarios causing `OverlappingFileLockException`.
2525

2626
**Changed**
2727

platform/jvm/capture-plugin/src/main/kotlin/io/bitdrift/capture/task/CLITask.kt

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -174,33 +174,40 @@ class BDCLIDownloader(
174174
}
175175

176176
fun downloadIfNeeded() {
177-
val parentDir = executableFilePath.parentFile
178-
if (!parentDir.exists() && !parentDir.mkdirs()) {
179-
throw IOException("Could not create path '${parentDir.absolutePath}' to contain the downloaded binary")
180-
}
177+
synchronized(lock) {
178+
if (executableFilePath.exists()) return
179+
180+
val parentDir = executableFilePath.parentFile
181+
if (!parentDir.exists() && !parentDir.mkdirs()) {
182+
throw IOException("Could not create path '${parentDir.absolutePath}' to contain the downloaded binary")
183+
}
181184

182-
val lockFilePath: Path = parentDir.toPath().resolve("bd.install.lock")
183-
FileChannel.open(
184-
lockFilePath,
185-
StandardOpenOption.CREATE,
186-
StandardOpenOption.WRITE,
187-
).use { fileChannel ->
188-
fileChannel.lock().use {
189-
// Check only after acquiring the lock
190-
if (executableFilePath.exists()) return
191-
192-
val tempPath = parentDir.toPath().resolve("bd.${UUID.randomUUID()}.tmp")
193-
try {
194-
Files.write(tempPath, bdcliDownloadLoc.toURL().readBytes())
195-
tempPath.markAsExecutable()
196-
tempPath.moveSafelyTo(executableFilePath.toPath())
197-
} catch (e: Exception) {
198-
runCatching { Files.deleteIfExists(tempPath) }
199-
throw IOException("Failed to download bd cli tool from $bdcliDownloadLoc", e)
185+
val lockFilePath: Path = parentDir.toPath().resolve("bd.install.lock")
186+
FileChannel.open(
187+
lockFilePath,
188+
StandardOpenOption.CREATE,
189+
StandardOpenOption.WRITE,
190+
).use { fileChannel ->
191+
fileChannel.lock().use {
192+
if (executableFilePath.exists()) return
193+
194+
val tempPath = parentDir.toPath().resolve("bd.${UUID.randomUUID()}.tmp")
195+
try {
196+
Files.write(tempPath, bdcliDownloadLoc.toURL().readBytes())
197+
tempPath.markAsExecutable()
198+
tempPath.moveSafelyTo(executableFilePath.toPath())
199+
} catch (e: Exception) {
200+
runCatching { Files.deleteIfExists(tempPath) }
201+
throw IOException(
202+
"Failed to download bd cli tool from $bdcliDownloadLoc",
203+
e
204+
)
205+
}
200206
}
201207
}
202208
}
203209
}
210+
204211
private fun Path.moveSafelyTo(dest: Path) {
205212
try {
206213
Files.move(
@@ -219,6 +226,10 @@ class BDCLIDownloader(
219226
throw IOException("Could not mark ${tempFile.absolutePath} as executable")
220227
}
221228
}
229+
230+
private companion object {
231+
private val lock = Any()
232+
}
222233
}
223234

224235
fun File.asXmlDocument(): Document {

0 commit comments

Comments
 (0)