summaryrefslogtreecommitdiff
path: root/src/library/scala/sys
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2013-04-30 12:33:41 -0700
committerSom Snytt <som.snytt@gmail.com>2013-05-15 13:18:06 -0700
commit538aa22ec8144430e778a34bc749eccb6f5dbf4c (patch)
tree3e647944fe935e63c6ba75463a20a95015f78a08 /src/library/scala/sys
parent92dbc00f1d0adbd8b89db88b7d42232a510e5e63 (diff)
downloadscala-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/scala/sys')
-rw-r--r--src/library/scala/sys/process/BasicIO.scala28
-rw-r--r--src/library/scala/sys/process/ProcessImpl.scala4
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()