Skip to content

Commit d62c26c

Browse files
committed
Ensure that preinitialization has completed before run returns
Previously, background preinitialization was started in response to an ApplicationEnvironmentPreparedEvent and would complete at an undetermined time later. This opened a window where SpringApplication run could return and background preinitialization could still be in progress. If, within this window, something attempted to configure the logging system, an IO failure could occur as logging on the background preinitialization thread would attempt to use resources that had been closed. This commit updates BackgroundPreinitializer so that it waits for preinitialization to have completed when it receives an application ready or application failed event. This prevents SpringApplication run from returning while preinitialization is still in progress, closing the window described above. With info level logging enabled it appears that background preinitialization consistently completes before the application ready event is published. As a result, waiting should have no adverse effect on performance in normal circumstances. With logging configured such that background preinitialization outputs a large volume of log messages (enabling trace logging for the root logger, for example), it will be slowed down sufficiently for waiting to be necessary. Closes gh-5669
1 parent 42eec50 commit d62c26c

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/BackgroundPreinitializer.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616

1717
package org.springframework.boot.autoconfigure;
1818

19+
import java.util.concurrent.CountDownLatch;
1920
import java.util.concurrent.atomic.AtomicBoolean;
2021

2122
import javax.validation.Validation;
2223

2324
import org.apache.catalina.mbeans.MBeanFactory;
2425

2526
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
27+
import org.springframework.boot.context.event.ApplicationFailedEvent;
28+
import org.springframework.boot.context.event.ApplicationReadyEvent;
29+
import org.springframework.boot.context.event.SpringApplicationEvent;
2630
import org.springframework.boot.logging.LoggingApplicationListener;
2731
import org.springframework.context.ApplicationListener;
2832
import org.springframework.core.annotation.Order;
@@ -40,14 +44,27 @@
4044
*/
4145
@Order(LoggingApplicationListener.DEFAULT_ORDER + 1)
4246
public class BackgroundPreinitializer
43-
implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
47+
implements ApplicationListener<SpringApplicationEvent> {
4448

4549
private static final AtomicBoolean preinitalizationStarted = new AtomicBoolean(false);
4650

51+
private static final CountDownLatch preinitializationComplete = new CountDownLatch(1);
52+
4753
@Override
48-
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
49-
if (preinitalizationStarted.compareAndSet(false, true)) {
50-
performPreinitialization();
54+
public void onApplicationEvent(SpringApplicationEvent event) {
55+
if (event instanceof ApplicationEnvironmentPreparedEvent) {
56+
if (preinitalizationStarted.compareAndSet(false, true)) {
57+
performPreinitialization();
58+
}
59+
}
60+
if (event instanceof ApplicationReadyEvent
61+
|| event instanceof ApplicationFailedEvent) {
62+
try {
63+
preinitializationComplete.await();
64+
}
65+
catch (InterruptedException ex) {
66+
Thread.currentThread().interrupt();
67+
}
5168
}
5269
}
5370

@@ -62,6 +79,7 @@ public void run() {
6279
runSafely(new ValidationInitializer());
6380
runSafely(new JacksonInitializer());
6481
runSafely(new ConversionServiceInitializer());
82+
preinitializationComplete.countDown();
6583
}
6684

6785
public void runSafely(Runnable runnable) {
@@ -80,6 +98,7 @@ public void runSafely(Runnable runnable) {
8098
// This will fail on GAE where creating threads is prohibited. We can safely
8199
// continue but startup will be slightly slower as the initialization will now
82100
// happen on the main thread.
101+
preinitializationComplete.countDown();
83102
}
84103
}
85104

0 commit comments

Comments
 (0)