google / ksp

Kotlin Symbol Processing API
https://github.com/google/ksp
Apache License 2.0
2.83k stars 265 forks source link

Dispatchers.IO Not Supported for File Creation #2011

Open mattshoe opened 2 months ago

mattshoe commented 2 months ago

Version: 2.0.0-1.0.21

Description I have a KSP plugin in which I may be creating many files. I am trying to optimize this by doing so concurrently with coroutines.

protected open suspend fun writeToFile(node: KSNode, fileData: GeneratedFile) = withContext(Dispatchers.IO) {
    codeGenerator.createNewFile(
        fileData.dependencies ?: Dependencies(false, node.containingFile!!),
        fileData.packageName,
        fileData.fileName
    ).bufferedWriter().use {
        it.write(fileData.output)
    }
}

But when using the plugin in a project, an indeterminate subset of createNewFile operations will always fail, with the following message:

[ksp] /Users/matthewshoemaker/repos/AutoRepo/AutoRepo.Test/src/main/kotlin/nocache/NoCacheScenarios.kt:15: Error processing FileLocation(filePath=/Users/matthewshoemaker/repos/AutoRepo/AutoRepo.Test/src/main/kotlin/nocache/NoCacheScenarios.kt, lineNumber=15):  java.lang.IllegalStateException: failed to make parent directories.

This only happens when I run the coroutines on the IO dispatcher. If I leave the coroutines on the Default dispatcher, this error never occurs and I can launch as many coroutines as i like to create the files.

I'd very much like to free up the Default thread pool for processing operations without bogging it down with so much IO.

I've tried creating my own schedulers and find the same issue. This suggests to me that the file creation logic used by KSP is just generally not being done in a thread safe manner under the hood

ansman commented 1 month ago

KSP is not thread safe and errors like this are expected.

Also, the IO dispatcher shares threads with the default dispatcher so it seems unlikely that the issue is the IO dispatcher.

Most likely you are hitting this error because you're launching more jobs concurrently than with the default dispatcher so you see these errors more frequently.