diff options
author | Paul Phillips <paulp@improving.org> | 2011-10-18 17:57:48 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-10-18 17:57:48 +0000 |
commit | ee365acb1752e7d789f32df3322a23526377f736 (patch) | |
tree | 5ec26212ca110f230c82ea070b3efdbf2602c161 | |
parent | d0a36c66cb18d94d15d44e5a04ed91ab00a43418 (diff) | |
download | scala-ee365acb1752e7d789f32df3322a23526377f736.tar.gz scala-ee365acb1752e7d789f32df3322a23526377f736.tar.bz2 scala-ee365acb1752e7d789f32df3322a23526377f736.zip |
Shutdown hook modification.
Don't mark shutdown hooks as daemon threads, although it does not seem
to make any difference. Instead have the code which waits for all
threads to be complete be smarted about which codes to monitor. No
review.
-rw-r--r-- | src/compiler/scala/tools/nsc/util/package.scala | 27 | ||||
-rw-r--r-- | src/library/scala/sys/ShutdownHookThread.scala | 1 | ||||
-rw-r--r-- | test/files/run/shutdownhooks.check | 3 | ||||
-rw-r--r-- | test/files/run/shutdownhooks.scala | 37 |
4 files changed, 60 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala index c5cd51a6f0..88e6c51e9f 100644 --- a/src/compiler/scala/tools/nsc/util/package.scala +++ b/src/compiler/scala/tools/nsc/util/package.scala @@ -26,19 +26,32 @@ package object util { def freqrank[T](xs: Traversable[(T, Int)]): List[(Int, T)] = xs.toList map (_.swap) sortBy (-_._1) - /** Execute code and then wait for all Threads created during its - * execution to complete. + /** Execute code and then wait for all non-daemon Threads + * created and begun during its execution to complete. */ def waitingForThreads[T](body: => T) = { - val ts1 = sys.allThreads() - val result = body - val ts2 = sys.allThreads() - val newThreads = ts2.toSet -- ts1 filterNot (_.isDaemon()) + val (result, created) = trackingThreads(body) + val threads = created filterNot (_.isDaemon) + + // As long as there are non-daemon, live threads (the latter + // condition should exclude shutdown hooks) we will wait. + while (threads exists (_.isAlive)) + threads filter (_.isAlive) foreach (_.join()) - newThreads foreach (_.join()) result } + /** Executes the code and returns the result and any threads + * which were created during its execution. + */ + def trackingThreads[T](body: => T): (T, Seq[Thread]) = { + val ts1 = sys.allThreads() + val result = body + val ts2 = sys.allThreads() + + (result, ts2 filterNot (ts1 contains _)) + } + /** Given a function and a block of code, evaluates code block, * calls function with milliseconds elapsed, and returns block result. */ diff --git a/src/library/scala/sys/ShutdownHookThread.scala b/src/library/scala/sys/ShutdownHookThread.scala index 9a4979cd07..018b71aefa 100644 --- a/src/library/scala/sys/ShutdownHookThread.scala +++ b/src/library/scala/sys/ShutdownHookThread.scala @@ -32,7 +32,6 @@ object ShutdownHookThread { val t = new ShutdownHookThread(hookName()) { override def run() = body } - t setDaemon true runtime addShutdownHook t t } diff --git a/test/files/run/shutdownhooks.check b/test/files/run/shutdownhooks.check new file mode 100644 index 0000000000..29956956e3 --- /dev/null +++ b/test/files/run/shutdownhooks.check @@ -0,0 +1,3 @@ +Fooblitzky! +main#shutdown. +Test#shutdown. diff --git a/test/files/run/shutdownhooks.scala b/test/files/run/shutdownhooks.scala new file mode 100644 index 0000000000..7fe5d129d6 --- /dev/null +++ b/test/files/run/shutdownhooks.scala @@ -0,0 +1,37 @@ +object Test { + scala.sys.addShutdownHook { + Thread.sleep(1000) + println("Test#shutdown.") + } + + def daemon() = { + val t = new Thread { + override def run() { + Thread.sleep(10000) + println("Hallelujah!") // should not see this + } + } + t.setDaemon(true) + t.start() + t + } + + def nonDaemon() = { + val t = new Thread { + override def run() { + Thread.sleep(100) + println("Fooblitzky!") + } + } + t.start() + t + } + + def main(args: Array[String]): Unit = { + daemon() + nonDaemon() + scala.sys.addShutdownHook { + println("main#shutdown.") + } + } +} |