Skip to content

Commit 91576f9

Browse files
committed
fix: fix concurrent bundled resource restore temp file collision
1 parent 9f5835b commit 91576f9

1 file changed

Lines changed: 30 additions & 15 deletions

File tree

app/src/main/kotlin/features/resources/runtime/AndroidResourceFileStore.kt

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -268,24 +268,39 @@ internal fun writeAtomically(
268268
target: File,
269269
write: (java.io.OutputStream) -> Unit,
270270
) {
271-
target.parentFile?.mkdirs()
272-
val tempFile = File(target.parentFile, "${target.name}.tmp")
273-
try {
274-
tempFile.outputStream().use(write)
275-
if (tempFile.length() <= 0) {
276-
tempFile.delete()
277-
error("${target.name} is empty")
278-
}
279-
if (target.exists()) {
280-
target.delete()
271+
val parent = target.parentFile ?: error("Parent directory is unavailable for ${target.absolutePath}")
272+
parent.mkdirs()
273+
synchronized(writeLockFor(target)) {
274+
val tempPrefix = "${target.name}.".let { prefix ->
275+
if (prefix.length >= 3) prefix else prefix.padEnd(3, '_')
281276
}
282-
if (!tempFile.renameTo(target)) {
277+
val tempFile = File.createTempFile(tempPrefix, ".tmp", parent)
278+
try {
279+
tempFile.outputStream().use(write)
280+
if (tempFile.length() <= 0) {
281+
tempFile.delete()
282+
error("${target.name} is empty")
283+
}
284+
if (target.exists() && !target.delete()) {
285+
tempFile.delete()
286+
error("Failed to replace ${target.name}")
287+
}
288+
if (!tempFile.renameTo(target)) {
289+
tempFile.delete()
290+
error("Failed to replace ${target.name}")
291+
}
292+
} catch (error: Throwable) {
283293
tempFile.delete()
284-
error("Failed to replace ${target.name}")
294+
throw error
285295
}
286-
} catch (error: Throwable) {
287-
tempFile.delete()
288-
throw error
296+
}
297+
}
298+
299+
private val WriteLocks = mutableMapOf<String, Any>()
300+
301+
private fun writeLockFor(target: File): Any {
302+
return synchronized(WriteLocks) {
303+
WriteLocks.getOrPut(target.absolutePath) { Any() }
289304
}
290305
}
291306

0 commit comments

Comments
 (0)