Fix Process.waitFor freeze on windows when gradle daemon is stopped during tests

This commit is contained in:
Alexey Tsvetkov
2016-03-10 16:28:44 +03:00
parent b2cffeeb24
commit d6c2f77125
2 changed files with 56 additions and 43 deletions
@@ -2,11 +2,12 @@ package org.jetbrains.kotlin.gradle
import com.google.common.io.Files
import org.gradle.api.logging.LogLevel
import org.jetbrains.kotlin.gradle.util.createGradleCommand
import org.jetbrains.kotlin.gradle.util.runProcess
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
import java.io.File
import java.io.InputStream
import kotlin.test.*
private val SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator")
@@ -42,29 +43,12 @@ abstract class BaseGradleIT {
ranDaemonVersions.clear()
}
fun createGradleCommand(tailParameters: List<String>): List<String> {
return if (isWindows())
listOf("cmd", "/C", "gradlew.bat") + tailParameters
else
listOf("/bin/bash", "./gradlew") + tailParameters
}
fun isWindows(): Boolean {
return System.getProperty("os.name")!!.contains("Windows")
}
fun stopDaemon(ver: String) {
println("Stopping gradle daemon v$ver")
val wrapperDir = File(resourcesRootFile, "GradleWrapper-$ver")
val cmd = createGradleCommand(arrayListOf("-stop"))
createProcess(cmd, wrapperDir).waitFor()
}
fun createProcess(cmd: List<String>, projectDir: File): Process {
val builder = ProcessBuilder(cmd)
builder.directory(projectDir)
builder.redirectErrorStream(true)
return builder.start()
val result = runProcess(cmd, wrapperDir)
assert(result.isSuccessful) { "Could not stop daemon: $result" }
}
@Synchronized
@@ -98,8 +82,9 @@ abstract class BaseGradleIT {
val kotlinSourcesListRegex = Regex("\\[KOTLIN\\] compile iteration: ([^\\r\\n]*)")
val javaSourcesListRegex = Regex("\\[DEBUG\\] \\[[^\\]]*JavaCompiler\\] Compiler arguments: ([^\\r\\n]*)")
}
val compiledKotlinSources : Iterable<File> by lazy { kotlinSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(", ").map { File(project.projectDir, it).canonicalFile } } }
val compiledJavaSources : Iterable<File> by lazy { javaSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(" ").filter { it.endsWith(".java", ignoreCase = true) }.map { File(it).canonicalFile } } }
val compiledKotlinSources: Iterable<File> by lazy { kotlinSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(", ").map { File(project.projectDir, it).canonicalFile } } }
val compiledJavaSources: Iterable<File> by lazy { javaSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(" ").filter { it.endsWith(".java", ignoreCase = true) }.map { File(it).canonicalFile } } }
}
fun Project.build(vararg tasks: String, options: BuildOptions = defaultBuildOptions(), check: CompiledProject.() -> Unit) {
@@ -116,13 +101,12 @@ abstract class BaseGradleIT {
private fun Project.runAndCheck(cmd: List<String>, check: CompiledProject.() -> Unit) {
val projectDir = File(workingDir, projectName)
if (!projectDir.exists())
if (!projectDir.exists()) {
setupWorkingDir()
}
val process = createProcess(cmd, projectDir)
val (output, resultCode) = readOutput(process)
CompiledProject(this, output, resultCode).check()
val result = runProcess(cmd, projectDir)
CompiledProject(this, result.output, result.exitCode).check()
}
fun CompiledProject.assertSuccessful(): CompiledProject {
@@ -221,22 +205,6 @@ abstract class BaseGradleIT {
private fun String.normalize() = this.lineSequence().joinToString(SYSTEM_LINE_SEPARATOR)
private fun readOutput(process: Process): Pair<String, Int> {
fun InputStream.readFully(): String {
val text = reader().readText()
close()
return text
}
val stdout = process.inputStream!!.readFully()
System.out.println(stdout)
val stderr = process.errorStream!!.readFully()
System.err.println(stderr)
val result = process.waitFor()
return stdout to result
}
fun copyRecursively(source: File, target: File) {
assertTrue(target.isDirectory)
val targetFile = File(target, source.name)
@@ -0,0 +1,45 @@
package org.jetbrains.kotlin.gradle.util
import java.io.File
class ProcessRunResult(
private val cmd: List<String>,
private val workingDir: File,
val exitCode: Int,
val output: String
) {
val isSuccessful: Boolean
get() = exitCode == 0
override fun toString(): String = """
Executing process was ${if (isSuccessful) "successful" else "unsuccessful"}
Command: ${cmd.joinToString()}
Working directory: ${workingDir.absolutePath}
Exit code: $exitCode
Output: $output
"""
}
fun runProcess(cmd: List<String>, workingDir: File): ProcessRunResult {
val builder = ProcessBuilder(cmd)
builder.directory(workingDir)
// redirectErrorStream merges stdout and stderr, so it can be get from process.inputStream
builder.redirectErrorStream(true)
val process = builder.start()
// important to read inputStream, otherwise the process may hang on some systems
val output = process.inputStream!!.bufferedReader().readText()
System.out.println(output)
val exitCode = process.waitFor()
return ProcessRunResult(cmd, workingDir, exitCode, output)
}
fun createGradleCommand(tailParameters: List<String>): List<String> {
return if (isWindows())
listOf("cmd", "/C", "gradlew.bat") + tailParameters
else
listOf("/bin/bash", "./gradlew") + tailParameters
}
private fun isWindows(): Boolean = System.getProperty("os.name")!!.contains("Windows")