@@ -18,7 +18,6 @@ import org.testcontainers.containers.wait.strategy.Wait
1818import spock.lang.Shared
1919
2020abstract class RedissonClientTest extends VersionedNamingTestBase {
21-
2221 @Shared
2322 RedisServer redisServer = new RedisContainer (DockerImageName . parse(" redis:6.2.6" )). waitingFor(Wait . forListeningPort())
2423
@@ -48,9 +47,17 @@ abstract class RedissonClientTest extends VersionedNamingTestBase {
4847 }
4948
5049 def cleanupSpec () {
51- lowLevelRedisClient. shutdown()
52- redissonClient. shutdown()
53- redisServer. stop()
50+ tryShutdown(" low-level redis client" ) {
51+ lowLevelRedisClient. shutdown()
52+ }
53+
54+ tryShutdown(" redisson client" ) {
55+ redissonClient. shutdown()
56+ }
57+
58+ tryShutdown(" redis server" ) {
59+ redisServer. stop()
60+ }
5461 }
5562
5663 def setup () {
@@ -65,6 +72,31 @@ abstract class RedissonClientTest extends VersionedNamingTestBase {
6572 }
6673 }
6774
75+ // Some shutdown paths in old Redisson versions can block forever.
76+ // In tests this is acceptable as best-effort cleanup, so run shutdown in
77+ // a daemon helper thread to make sure teardown cannot keep the JVM alive.
78+ private static void tryShutdown (String component , Closure shutdownAction ) {
79+ Thread shutdownThread = new Thread ({
80+ try {
81+ shutdownAction. call()
82+ } catch (Throwable e) {
83+ println " Unexpected error during shutting down of ${ component} : ${ e.message} "
84+ }
85+ })
86+ shutdownThread. daemon = true
87+ shutdownThread. start()
88+
89+ try {
90+ shutdownThread. join(10_000L)
91+ } catch (InterruptedException ignored) {
92+ Thread . currentThread(). interrupt()
93+ }
94+
95+ if (shutdownThread. isAlive()) {
96+ println " Timed out shutting down of ${ component} "
97+ }
98+ }
99+
68100 def " bucket set command" () {
69101 when :
70102 redissonClient. getBucket(" foo" ). set(" bar" )
@@ -371,4 +403,3 @@ class RedissonClientV1ForkedTest extends RedissonClientTest {
371403 return " redis.command"
372404 }
373405}
374-
0 commit comments