Skip to content

SpringApplicationShutdownHook hangs in Mqttv5ClientManager stop() if client never was connected #9112

@in-fke

Description

@in-fke

In what version(s) of Spring Integration are you seeing this issue?

spring-integration-mqtt-6.2.4

Describe the bug

Mqttv5ClientManager hangs in stop() if never was connected.
Mqttv3ClientManager may be affected as well.

see https://www.linkedin.com/pulse/mqtt-paho-tomcat-stop-using-shutdownsh-fails-sudhir-ravindramohan/

To Reproduce

  1. Instantiate Mqttv5ClientManager with automaticReconnect, while there is no MQTT Broker to connect to
  2. Shutdown Spring Application
  3. Pause in Debuggger to see hang as follows
Thread [SpringApplicationShutdownHook] (Suspended)	
	waiting for: Object  (id=171)	
	Object.wait(long) line: not available [native method]	
	ClientState.quiesce(long) line: 1497	
	ClientComms.disconnectForcibly(long, long, boolean, int, MqttProperties) line: 600	
	ClientComms.disconnectForcibly(long, long, int, MqttProperties) line: 576	
	MqttAsyncClient.disconnectForcibly(long, long, int, MqttProperties) line: 888	
	MqttAsyncClient.disconnectForcibly(long) line: 873	
	MqttListener$1.stop() line: 49	
	MqttListener$1(SmartLifecycle).stop(Runnable) line: 117	
	DefaultLifecycleProcessor.doStop(Map<String,Lifecycle>, String, CountDownLatch, Set<String>) line: 344	
	DefaultLifecycleProcessor$LifecycleGroup.stop() line: 483	
	0x0000021f959848c8.accept(Object) line: not available	
	TreeMap$Values(Iterable<T>).forEach(Consumer<? super T>) line: 75	
	DefaultLifecycleProcessor.stopBeans() line: 313	
	DefaultLifecycleProcessor.onClose() line: 214	
	AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).doClose() line: 1136	
	AnnotationConfigServletWebServerApplicationContext(ServletWebServerApplicationContext).doClose() line: 174	
	AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).close() line: 1090	
	SpringApplicationShutdownHook.closeAndWait(ConfigurableApplicationContext) line: 145	
	0x0000021f95984230.accept(Object) line: not available	
	LinkedHashSet<E>(Iterable<T>).forEach(Consumer<? super T>) line: 75	
	SpringApplicationShutdownHook.run() line: 114	
	Thread.run() line: 840	

Expected behavior

Troubling code
https://github.com/spring-projects/spring-integration/blob/main/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/core/Mqttv5ClientManager.java#L153
and possibly
https://github.com/spring-projects/spring-integration/blob/main/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/core/Mqttv3ClientManager.java#L151

Sample

Replacing the line

client.disconnectForcibly(getDisconnectCompletionTimeout());

by

if (client.isConnected()) {
    client.disconnect(0).waitForCompletion(getDisconnectCompletionTimeout());
}

makes it work in this case. Not sure if that would be the universal solution. Not tested with Mqttv3ClientManager.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions