Skip to content

MqttClient.IsConnected false after successful connect #2180

@ghost

Description

Describe the bug

In MqttClient in reconnect scenarios it happens, that after a successful reconnect, the IsConnect flag stays false.
That leads to a loop of reconnects in our code, which sometimes go on for several minutes until IsConnected finally transitions to true.

Which component is your bug related to?

  • Client
  • Server (maybe?)

To Reproduce

MQTTnet v5.0.1
MQTTnet.Server v5.0.1
MQTTnet.Server is running as broker in the same process, connected via tcp loopback adapter.
Running under Windows, with .NET 8

We have a reconnect mechanism in place, as suggested in the samples, using an endless loop and Task.Delay.
This issue never happens at initial disconnect, only at reconnect.
The client object is reused after a connection loss.

it does not happen everytime!
It's pretty hard to reproduce while productive use.

Expected behavior

IsConnected should be true when connect states successfull.
OR ConnectResult should not return Success, when IsConnected was not set to true.

Additional context / logging

when reconnection:

  1. Connecting event from client gets fired (which is expected)
  2. ClientDisconnected event from broker (for this client) get fired. DiconnectType: Takeover (which is expected IMO)
  3. "Disconnected" log from client (not expected IMO)
  4. "Client '...' Connection stopped" log from server (I guess this is from the "old" ConnectedClient, due to session takeover)

Code example

client options:

var options = ConfigureClientOptions(clientOptionsBuilder
             .WithClientId("someClientIdString")
             .WithKeepAlivePeriod(Timespan.FromSeconds(10))
            .WithCleanStart()
            .WithSessionExpiryInterval(0)
            .Build();

we save that options in a variable and pass it as parameter for connect and reconnect.

how we (re-)connect, and the Debug.Assert which fails:

 var result = await Client.ConnectAsync(options, combinedCts.Token);
            if (result.ResultCode != MqttClientConnectResultCode.Success)
            {
                _logger.LogCritical(
                    "MqttClient {mqttClientId} failed to connect to broker! ResultCode: {resultCode}, Reason: {reason}.",
                    ClientId, result.ResultCode, result.ReasonString);
                return MqttConnectResult.FailedOrCancelled;
            }

            Debug.Assert(Client.IsConnected);
            return MqttConnectResult.Success;

Testing/reproduce code

Tryining to reproduce it (and sometimes successful), we put this code in our reconnect loop:

  while (!_disposed && !stopSignal.IsCancellationRequested)
            {

                // test-code starts
               // -----------

                // sidenote: in productive environments we wait for 500ms until we check IsConnected
                await Task.Delay(TimeSpan.FromSeconds(20), stopSignal);

                await Client.DisconnectAsync(reason: MqttClientDisconnectOptionsReason.AdministrativeAction, cancellationToken: stopSignal);
                
                await Task.Delay(TimeSpan.FromSeconds(2), stopSignal);

                // ----------
               // end of test code

                if (Client.IsConnected)
                {
                    continue;
                }
                var connectResult = await InternalConnectMethodAsync(options, stopSignal);

}

as already said, most of the time the reconnect works without problems.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions