GracefulShutdownSettled

class GracefulShutdownSettled @JvmOverloads constructor(timeout: Duration = DEFAULT_TIMEOUT, threads: () -> Collection<Thread> = { Thread.getAllStackTraces().keys }) : SmartLifecycle

Waits, between the public server's graceful shutdown and its stop, for the thread of that shutdown to end, at most timeout: a workaround of a race in Spring Boot 4.1.1 (spring-boot-reactor-netty, and 3.5.x before it), to remove once the host builds on a Spring Boot that fixes it (below).

The race, in org.springframework.boot.reactor.netty.GracefulShutdown (https://github.com/spring-projects/spring-boot/blob/v4.1.1/module/spring-boot-reactor-netty/src/main/java/org/springframework/boot/reactor/netty/GracefulShutdown.java): doShutdown, on the netty-shutdown thread, calls callback.shutdownComplete(...) and only then, in finally, sets shutdownThread = null and shuttingDown = false. The callback lets the lifecycle go on to the server's stop (WebServerStartStopLifecycle, the next phase), which calls abort(): it reads shutdownThread, then polls while (!shuttingDown) sleep(50). When the finally runs between the two, abort() polls forever, and the context's close hangs there with no Wow frame on its stack (seen as PaymentServerTest.close stuck in GracefulShutdown.abort). Fixed upstream in Spring Boot 4.1.2 (https://github.com/spring-projects/spring-boot/issues/52196; 4.0.9 for the 4.0 line, https://github.com/spring-projects/spring-boot/issues/52119): remove this lifecycle and its bean once the host builds on 4.1.2 or later.

Once that thread has ended, abort() finds none and returns at once. When the graceful shutdown outlasted its phase, the thread is still shutting down after timeout, which is logged as a warning, and abort() interrupts it.

Constructors

Link copied to clipboard
constructor(timeout: Duration = DEFAULT_TIMEOUT, threads: () -> Collection<Thread> = { Thread.getAllStackTraces().keys })

Types

Link copied to clipboard

Properties

Link copied to clipboard
open override val isRunning: Boolean
Link copied to clipboard
open override val phase: Int

Functions

Link copied to clipboard
open override fun getPhase(): Int
Link copied to clipboard
open override fun isRunning(): Boolean
Link copied to clipboard
open override fun start()
Link copied to clipboard
open override fun stop()