Commit b47af199 authored by Dave Syer's avatar Dave Syer Committed by Phillip Webb

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
parent 983484f4
...@@ -27,6 +27,7 @@ import org.springframework.boot.devtools.classpath.ClassPathChangedEvent; ...@@ -27,6 +27,7 @@ import org.springframework.boot.devtools.classpath.ClassPathChangedEvent;
import org.springframework.boot.devtools.classpath.ClassPathFileSystemWatcher; import org.springframework.boot.devtools.classpath.ClassPathFileSystemWatcher;
import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy; import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy;
import org.springframework.boot.devtools.classpath.PatternClassPathRestartStrategy; 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.livereload.LiveReloadServer;
import org.springframework.boot.devtools.restart.ConditionalOnInitializedRestarter; import org.springframework.boot.devtools.restart.ConditionalOnInitializedRestarter;
import org.springframework.boot.devtools.restart.RestartScope; import org.springframework.boot.devtools.restart.RestartScope;
...@@ -103,11 +104,14 @@ public class LocalDevToolsAutoConfiguration { ...@@ -103,11 +104,14 @@ public class LocalDevToolsAutoConfiguration {
@Autowired @Autowired
private DevToolsProperties properties; private DevToolsProperties properties;
private final FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ClassPathFileSystemWatcher classPathFileSystemWatcher() { public ClassPathFileSystemWatcher classPathFileSystemWatcher() {
URL[] urls = Restarter.getInstance().getInitialUrls(); URL[] urls = Restarter.getInstance().getInitialUrls();
return new ClassPathFileSystemWatcher(classPathRestartStrategy(), urls); return new ClassPathFileSystemWatcher(this.fileSystemWatcher,
classPathRestartStrategy(), urls);
} }
@Bean @Bean
...@@ -120,6 +124,7 @@ public class LocalDevToolsAutoConfiguration { ...@@ -120,6 +124,7 @@ public class LocalDevToolsAutoConfiguration {
@EventListener @EventListener
public void onClassPathChanged(ClassPathChangedEvent event) { public void onClassPathChanged(ClassPathChangedEvent event) {
if (event.isRestartRequired()) { if (event.isRestartRequired()) {
this.fileSystemWatcher.stop();
Restarter.getInstance().restart(); Restarter.getInstance().restart();
} }
} }
......
...@@ -72,11 +72,11 @@ public class ClassPathFileSystemWatcher implements InitializingBean, DisposableB ...@@ -72,11 +72,11 @@ public class ClassPathFileSystemWatcher implements InitializingBean, DisposableB
* @param restartStrategy the classpath restart strategy * @param restartStrategy the classpath restart strategy
* @param urls the URLs to watch * @param urls the URLs to watch
*/ */
protected ClassPathFileSystemWatcher(FileSystemWatcher fileSystemWatcher, public ClassPathFileSystemWatcher(FileSystemWatcher fileSystemWatcher,
ClassPathRestartStrategy restartStrategy, URL[] urls) { ClassPathRestartStrategy restartStrategy, URL[] urls) {
Assert.notNull(fileSystemWatcher, "FileSystemWatcher must not be null"); Assert.notNull(fileSystemWatcher, "FileSystemWatcher must not be null");
Assert.notNull(urls, "Urls must not be null"); Assert.notNull(urls, "Urls must not be null");
this.fileSystemWatcher = new FileSystemWatcher(); this.fileSystemWatcher = fileSystemWatcher;
this.restartStrategy = restartStrategy; this.restartStrategy = restartStrategy;
addUrls(urls); addUrls(urls);
} }
......
...@@ -199,13 +199,16 @@ public class FileSystemWatcher { ...@@ -199,13 +199,16 @@ public class FileSystemWatcher {
Thread thread = this.watchThread; Thread thread = this.watchThread;
if (thread != null) { if (thread != null) {
this.remainingScans.set(remainingScans); this.remainingScans.set(remainingScans);
try { if (Thread.currentThread() != thread) {
thread.join(); try {
} thread.join();
catch (InterruptedException ex) { }
Thread.currentThread().interrupt(); catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
} }
this.watchThread = null; this.watchThread = null;
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment