Last active
August 29, 2015 14:06
-
-
Save rubyu/9b1a82bfe0ddcc2df6e5 to your computer and use it in GitHub Desktop.
sys.processで複数のProcessBuilderを接続した場合にブロッキングが発生する問題(2.12.0-M1で解決予定) ref: http://qiita.com/rubyu/items/1c28f0b21dbd4d06262b
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys.process._ | |
def input = new ByteArrayInputStream("input".getBytes) | |
// wcコマンドにinputという文字列を標準入力から渡す x 100回 | |
for (i <- 0 until 100) | |
"wc" #< input !! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private[process] class PipedProcesses(a: ProcessBuilder, b: ProcessBuilder, defaultIO: ProcessIO, toError: Boolean) extends CompoundProcess { | |
protected[this] override def runAndExitValue() = { | |
val currentSource = new SyncVar[Option[InputStream]] | |
val pipeOut = new PipedOutputStream | |
val source = new PipeSource(currentSource, pipeOut, a.toString) | |
source.start() | |
val pipeIn = new PipedInputStream(pipeOut) | |
val currentSink = new SyncVar[Option[OutputStream]] | |
val sink = new PipeSink(pipeIn, currentSink, b.toString) | |
sink.start() | |
def handleOutOrError(fromOutput: InputStream) = currentSource put Some(fromOutput) | |
val firstIO = | |
if (toError) | |
defaultIO.withError(handleOutOrError) | |
else | |
defaultIO.withOutput(handleOutOrError) | |
// この処理より | |
val secondIO = defaultIO.withInput(toInput => currentSink put Some(toInput)) | |
val second = b.run(secondIO) | |
val first = a.run(firstIO) | |
try { | |
runInterruptible { | |
val exit1 = first.exitValue() | |
currentSource put None | |
// こっちのが早いタイミングで実行されると、プロセスが正常に接続されない | |
currentSink put None | |
val exit2 = second.exitValue() | |
// Since file redirection (e.g. #>) is implemented as a piped process, | |
// we ignore its exit value so cmd #> file doesn't always return 0. | |
if (b.hasExitValue) exit2 else exit1 | |
} { | |
first.destroy() | |
second.destroy() | |
} | |
} | |
finally { | |
BasicIO close pipeIn | |
BasicIO close pipeOut | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment