diff options
author | Som Snytt <som.snytt@gmail.com> | 2013-04-30 12:33:41 -0700 |
---|---|---|
committer | Som Snytt <som.snytt@gmail.com> | 2013-05-15 13:18:06 -0700 |
commit | 538aa22ec8144430e778a34bc749eccb6f5dbf4c (patch) | |
tree | 3e647944fe935e63c6ba75463a20a95015f78a08 /src/library | |
parent | 92dbc00f1d0adbd8b89db88b7d42232a510e5e63 (diff) | |
download | scala-538aa22ec8144430e778a34bc749eccb6f5dbf4c.tar.gz scala-538aa22ec8144430e778a34bc749eccb6f5dbf4c.tar.bz2 scala-538aa22ec8144430e778a34bc749eccb6f5dbf4c.zip |
SI-6488 Interrupt i/o threads on process destroy
The previous fix uses Thread.stop to stop the threads which
drain outputs, but should do something orderly.
This commit interrupts the threads, which must check isInterrupted
before attempting further i/o.
The reading thread will suppress either the interruption or the
IOException cited in the ticket.
Similarly, i/o handlers must preserve and communicate interrupted
status.
The modest goal of this fix is to ameliorate any stack traces
when the process is destroyed.
The test runs itself as a sample process with output.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/sys/process/BasicIO.scala | 28 | ||||
-rw-r--r-- | src/library/scala/sys/process/ProcessImpl.scala | 4 |
2 files changed, 20 insertions, 12 deletions
diff --git a/src/library/scala/sys/process/BasicIO.scala b/src/library/scala/sys/process/BasicIO.scala index 58517de402..b31bbf0540 100644 --- a/src/library/scala/sys/process/BasicIO.scala +++ b/src/library/scala/sys/process/BasicIO.scala @@ -162,21 +162,29 @@ object BasicIO { */ def processFully(processLine: String => Unit): InputStream => Unit = in => { val reader = new BufferedReader(new InputStreamReader(in)) - processLinesFully(processLine)(reader.readLine) - reader.close() + try processLinesFully(processLine)(reader.readLine) + finally reader.close() } /** Calls `processLine` with the result of `readLine` until the latter returns - * `null`. - */ + * `null` or the current thread is interrupted. + */ def processLinesFully(processLine: String => Unit)(readLine: () => String) { - def readFully() { - val line = readLine() - if (line != null) { - processLine(line) - readFully() + def working = (Thread.currentThread.isInterrupted == false) + def halting = { Thread.currentThread.interrupt(); null } + def readFully(): Unit = + if (working) { + val line = + try readLine() + catch { + case _: InterruptedException => halting + case e: IOException if !working => halting + } + if (line != null) { + processLine(line) + readFully() + } } - } readFully() } diff --git a/src/library/scala/sys/process/ProcessImpl.scala b/src/library/scala/sys/process/ProcessImpl.scala index 7a5fc4ef9b..2b7fcdeb73 100644 --- a/src/library/scala/sys/process/ProcessImpl.scala +++ b/src/library/scala/sys/process/ProcessImpl.scala @@ -223,8 +223,8 @@ private[process] trait ProcessImpl { p.exitValue() } override def destroy() = { - try{ - outputThreads foreach (_.stop()) + try { + outputThreads foreach (_.interrupt()) // on destroy, don't bother consuming any more output p.destroy() } finally inputThread.interrupt() |