From b47af19920bbf180c59da40c722c96033dcaa6f0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 4 Jun 2015 10:27:03 +0100 Subject: [PATCH] Stop file watcher as soon as a change is detected The FileWatcher sometimes generates multiple events for a single change and if there is a slow shutdown hook the second one can come in before the context is closed, leaving it in a tricky state. This change attempts to stop the file watcher as soon as it detects a change (the stop() method is called in the listener, which normally happens in the same thread as the scan). Fixes gh-3097 --- .../LocalDevToolsAutoConfiguration.java | 7 ++++++- .../classpath/ClassPathFileSystemWatcher.java | 4 ++-- .../boot/devtools/filewatch/FileSystemWatcher.java | 13 ++++++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java index 880d76b3e8..36da42b647 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.boot.devtools.classpath.ClassPathChangedEvent; import org.springframework.boot.devtools.classpath.ClassPathFileSystemWatcher; import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy; import org.springframework.boot.devtools.classpath.PatternClassPathRestartStrategy; +import org.springframework.boot.devtools.filewatch.FileSystemWatcher; import org.springframework.boot.devtools.livereload.LiveReloadServer; import org.springframework.boot.devtools.restart.ConditionalOnInitializedRestarter; import org.springframework.boot.devtools.restart.RestartScope; @@ -103,11 +104,14 @@ public class LocalDevToolsAutoConfiguration { @Autowired private DevToolsProperties properties; + private final FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); + @Bean @ConditionalOnMissingBean public ClassPathFileSystemWatcher classPathFileSystemWatcher() { URL[] urls = Restarter.getInstance().getInitialUrls(); - return new ClassPathFileSystemWatcher(classPathRestartStrategy(), urls); + return new ClassPathFileSystemWatcher(this.fileSystemWatcher, + classPathRestartStrategy(), urls); } @Bean @@ -120,6 +124,7 @@ public class LocalDevToolsAutoConfiguration { @EventListener public void onClassPathChanged(ClassPathChangedEvent event) { if (event.isRestartRequired()) { + this.fileSystemWatcher.stop(); Restarter.getInstance().restart(); } } diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileSystemWatcher.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileSystemWatcher.java index 2a4148e784..a32d806636 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileSystemWatcher.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileSystemWatcher.java @@ -72,11 +72,11 @@ public class ClassPathFileSystemWatcher implements InitializingBean, DisposableB * @param restartStrategy the classpath restart strategy * @param urls the URLs to watch */ - protected ClassPathFileSystemWatcher(FileSystemWatcher fileSystemWatcher, + public ClassPathFileSystemWatcher(FileSystemWatcher fileSystemWatcher, ClassPathRestartStrategy restartStrategy, URL[] urls) { Assert.notNull(fileSystemWatcher, "FileSystemWatcher must not be null"); Assert.notNull(urls, "Urls must not be null"); - this.fileSystemWatcher = new FileSystemWatcher(); + this.fileSystemWatcher = fileSystemWatcher; this.restartStrategy = restartStrategy; addUrls(urls); } diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/filewatch/FileSystemWatcher.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/filewatch/FileSystemWatcher.java index a57966d894..722807e958 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/filewatch/FileSystemWatcher.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/filewatch/FileSystemWatcher.java @@ -199,13 +199,16 @@ public class FileSystemWatcher { Thread thread = this.watchThread; if (thread != null) { this.remainingScans.set(remainingScans); - try { - thread.join(); - } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + if (Thread.currentThread() != thread) { + try { + thread.join(); + } + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } } this.watchThread = null; } } + }