From 0fea8ec12d3c485365f078c59dcc9fb186862a6c Mon Sep 17 00:00:00 2001 From: timtay-microsoft Date: Thu, 2 Nov 2023 11:23:28 -0700 Subject: [PATCH] fix(iot-dev): fix bug where client opening with retry isn't cancelled by close If a client is struggling to open the connection (no network scenarios, for example), then users should be able to close the client without waiting for the retry to expire #1759 --- .../com/microsoft/azure/sdk/iot/device/DeviceIO.java | 4 ++++ .../sdk/iot/device/transport/IotHubTransport.java | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/DeviceIO.java b/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/DeviceIO.java index 2d08fb11fc..ee87d3d31e 100644 --- a/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/DeviceIO.java +++ b/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/DeviceIO.java @@ -206,6 +206,10 @@ private void stopReconnectThreads() */ void close() { + // Notify the transport layer that the user wants to close the connection. This + // will end any "open with retry" operations. Once any running open calls have ended, + // the state lock will be released and this close operation can proceed + this.transport.setClosing(true); synchronized (this.stateLock) { if (state == IotHubConnectionStatus.DISCONNECTED) diff --git a/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/transport/IotHubTransport.java b/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/transport/IotHubTransport.java index 2989540157..ab99e0820c 100644 --- a/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/transport/IotHubTransport.java +++ b/iothub/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/transport/IotHubTransport.java @@ -16,6 +16,7 @@ import com.microsoft.azure.sdk.iot.device.transport.https.exceptions.UnauthorizedException; import com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection; import com.microsoft.azure.sdk.iot.device.transport.mqtt.exceptions.MqttUnauthorizedException; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import javax.net.ssl.SSLContext; @@ -119,6 +120,7 @@ public class IotHubTransport implements IotHubListener private final boolean useIdentifiableThreadNames; // Flag set when close() starts. Acts as a signal to any running reconnection logic to not try again. + @Setter private boolean isClosing; // Used to store the CorrelationCallbackMessage, context, and start time for a correlationId @@ -477,9 +479,16 @@ public void open(boolean withRetry) throws TransportException, IotHubClientExcep int connectionAttempt = 0; long startTime = System.currentTimeMillis(); - // this loop either ends in throwing an exception when retry expires, or by a break statement upon a successful openConnection() call + // this loop either ends in throwing an exception when retry expires, + // a break statement upon a successful openConnection() call, + // or the user attempts to close the client while (true) { + if (this.isClosing) + { + throw new TransportException("Client was closed while attempting to open the connection"); + } + RetryPolicy retryPolicy = isMultiplexing ? multiplexingRetryPolicy : this.getDefaultConfig().getRetryPolicy(); try