From 5df1d8e23f8283fe56786784339d1ff1fcce6f8e Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Fri, 1 Dec 2017 12:39:59 -0800 Subject: [PATCH] Cache watch service I noticed that my custom WatchService was never cleaned up by sbt and realized that after every build we were making a new WatchService. At the same time, we were reusing the WatchState from the previous run, which was using the original WatchService. This was particularly problematic because it prevented us from registering any paths with the new watch service. This may have prevented some of the file updates from being seen by the watch service. Moreover, because we lost the reference to the original WatchService, there was no way to clean it up, which was a resource leak. May be related to #3775, #3695 --- main-command/src/main/scala/sbt/Watched.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index fa1dee03f..8b8385b61 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -94,7 +94,7 @@ object Watched { @tailrec def shouldTerminate: Boolean = (System.in.available > 0) && (watched.terminateWatch(System.in.read()) || shouldTerminate) val sources = watched.watchSources(s) - val service = watched.watchService() + val service = s get ContinuousWatchService getOrElse watched.watchService() val watchState = s get ContinuousState getOrElse WatchState.empty(service, sources) if (watchState.count > 0) @@ -115,15 +115,21 @@ object Watched { if (triggered) { printIfDefined(watched triggeredMessage newWatchState) - (ClearOnFailure :: next :: FailureWall :: repeat :: s).put(ContinuousState, newWatchState) + (ClearOnFailure :: next :: FailureWall :: repeat :: s) + .put(ContinuousState, newWatchState) + .put(ContinuousWatchService, service) } else { while (System.in.available() > 0) System.in.read() service.close() - s.remove(ContinuousState) + s.remove(ContinuousState).remove(ContinuousWatchService) } } val ContinuousState = AttributeKey[WatchState]("watch state", "Internal: tracks state for continuous execution.") + + val ContinuousWatchService = + AttributeKey[WatchService]("watch service", + "Internal: tracks watch service for continuous execution.") val Configuration = AttributeKey[Watched]("watched-configuration", "Configures continuous execution.")