[K/N] Workaround waitFor in HostExecutor for Windows ^KT-65113
This commit is contained in:
committed by
Space Team
parent
0258e71bd5
commit
5ee726558f
+34
-1
@@ -156,6 +156,39 @@ private fun <T> ProcessBuilder.scoped(logger: Logger, block: suspend CoroutineSc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SleeperWithBackoff {
|
||||||
|
// Start with exponential backoff, then try 150ms for a while, and finally settle on a second.
|
||||||
|
private val backoffMilliseconds = longArrayOf(10, 20, 40, 80, 150, 150, 150, 150, 150)
|
||||||
|
private val maxBackoffMilliseconds = 1000L
|
||||||
|
private var nextIndex = 0
|
||||||
|
|
||||||
|
private val nextBackoffMilliseconds: Long
|
||||||
|
get() = backoffMilliseconds.getOrNull(nextIndex++) ?: maxBackoffMilliseconds
|
||||||
|
|
||||||
|
fun sleep() {
|
||||||
|
Thread.sleep(nextBackoffMilliseconds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Process.waitFor(timeout: Duration): Boolean {
|
||||||
|
if (!HostManager.hostIsMingw)
|
||||||
|
return waitFor(timeout.inWholeMilliseconds, TimeUnit.MILLISECONDS)
|
||||||
|
// KT-65113: Looks like there's a race in waitFor implementation for Windows. It can wait for the entire `timeout` but the process'
|
||||||
|
// exitValue would be 0.
|
||||||
|
if (!isAlive)
|
||||||
|
return true
|
||||||
|
if (!timeout.isPositive())
|
||||||
|
return false
|
||||||
|
val deadline = TimeSource.Monotonic.markNow() + timeout
|
||||||
|
val sleeper = SleeperWithBackoff()
|
||||||
|
do {
|
||||||
|
sleeper.sleep()
|
||||||
|
if (!isAlive)
|
||||||
|
break
|
||||||
|
} while (deadline.hasNotPassedNow())
|
||||||
|
return !isAlive
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Executor] that runs the process on the host system.
|
* [Executor] that runs the process on the host system.
|
||||||
*/
|
*/
|
||||||
@@ -181,7 +214,7 @@ class HostExecutor : Executor {
|
|||||||
}.scoped(logger) { process ->
|
}.scoped(logger) { process ->
|
||||||
val streams = pumpStreams(logger, process, request.stdin, request.stdout, request.stderr)
|
val streams = pumpStreams(logger, process, request.stdin, request.stdout, request.stderr)
|
||||||
val (isTimeout, duration) = measureTimedValue {
|
val (isTimeout, duration) = measureTimedValue {
|
||||||
!process.waitFor(request.timeout.inWholeMilliseconds, TimeUnit.MILLISECONDS)
|
!process.waitFor(request.timeout)
|
||||||
}
|
}
|
||||||
if (isTimeout) {
|
if (isTimeout) {
|
||||||
logger.warning("Timeout running $commandLine in $duration")
|
logger.warning("Timeout running $commandLine in $duration")
|
||||||
|
|||||||
Reference in New Issue
Block a user