This commit is contained in:
Yasumasa Suenaga 2025-06-30 23:28:26 +03:00 committed by GitHub
commit 4b409afcc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 17 deletions

View File

@ -683,22 +683,20 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
*/ */
private class CracResourceAdapter implements org.crac.Resource { private class CracResourceAdapter implements org.crac.Resource {
private @Nullable CyclicBarrier barrier; private CyclicBarrier stepToRestore = new CyclicBarrier(2);
private CyclicBarrier finishRestore = new CyclicBarrier(2);
private void preventShutdown() {
waitBarrier(this.stepToRestore);
// Checkpoint happens here
waitBarrier(this.finishRestore);
}
@Override @Override
public void beforeCheckpoint(org.crac.Context<? extends org.crac.Resource> context) { public void beforeCheckpoint(org.crac.Context<? extends org.crac.Resource> context) {
// A non-daemon thread for preventing an accidental JVM shutdown before the checkpoint Thread thread = new Thread(this::preventShutdown, "prevent-shutdown");
this.barrier = new CyclicBarrier(2);
Thread thread = new Thread(() -> {
awaitPreventShutdownBarrier();
// Checkpoint happens here
awaitPreventShutdownBarrier();
}, "prevent-shutdown");
thread.setDaemon(false); thread.setDaemon(false);
thread.start(); thread.start();
awaitPreventShutdownBarrier();
logger.debug("Stopping Spring-managed lifecycle beans before JVM checkpoint"); logger.debug("Stopping Spring-managed lifecycle beans before JVM checkpoint");
stopForRestart(); stopForRestart();
@ -706,11 +704,24 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
@Override @Override
public void afterRestore(org.crac.Context<? extends org.crac.Resource> context) { public void afterRestore(org.crac.Context<? extends org.crac.Resource> context) {
// Unlock barrier for beforeCheckpoint
try {
this.stepToRestore.await();
}
catch (Exception ex) {
logger.trace("Exception from stepToRestore barrier", ex);
}
logger.info("Restarting Spring-managed lifecycle beans after JVM restore"); logger.info("Restarting Spring-managed lifecycle beans after JVM restore");
restartAfterStop(); restartAfterStop();
// Barrier for prevent-shutdown thread not needed anymore // Unlock barrier for afterRestore to shutdown "prevent-shutdown" thread
this.barrier = null; try {
this.finishRestore.await();
}
catch (Exception ex) {
logger.trace("Exception from stepToRestore barrier", ex);
}
if (!checkpointOnRefresh) { if (!checkpointOnRefresh) {
logger.info("Spring-managed lifecycle restart completed (restored JVM running for " + logger.info("Spring-managed lifecycle restart completed (restored JVM running for " +
@ -718,11 +729,9 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
} }
} }
private void awaitPreventShutdownBarrier() { private void waitBarrier(CyclicBarrier barrier) {
try { try {
if (this.barrier != null) { barrier.await();
this.barrier.await();
}
} }
catch (Exception ex) { catch (Exception ex) {
logger.trace("Exception from prevent-shutdown barrier", ex); logger.trace("Exception from prevent-shutdown barrier", ex);