Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Program not exiting when using manual acknowledgment and publishing with QoS 0 #462

Closed
evisa-lumani opened this issue Jan 26, 2021 · 2 comments · Fixed by #475
Closed

Program not exiting when using manual acknowledgment and publishing with QoS 0 #462

evisa-lumani opened this issue Jan 26, 2021 · 2 comments · Fixed by #475
Assignees
Labels
Milestone

Comments

@evisa-lumani
Copy link

We are observing a behavior where our application using the HiveMQ MQTT client doesn't quit as expected, when using manual acknowledgment and publishing with QoS 0.

We tested with:

  • Java version 1.8.0_192 of Oracle, and OpenJDK 11
  • local HiveMQ broker as Docker container (hivemq/hivemq-ce:2020.6)
  • hivemq-mqtt-client version 1.2.1

To Reproduce

To reproduce the behavior, the following clients can be used:

  • A client publishing with QoS 0.
Mqtt5ClientBuilder mqttClientBuilder = MqttClient.builder()
                                                 .identifier("client-publisher")
                                                 .serverHost("localhost")
                                                 .serverPort(1883)
                                                 .useMqttVersion5();
Mqtt5RxClient mqttClient = mqttClientBuilder.buildRx();

mqttClient.connect(Mqtt5Connect.builder().build()).blockingGet();
System.out.println("Connected to MQTT Broker");

MqttQos pubQoS = MqttQos.AT_MOST_ONCE;
mqttClient.toBlocking().publishWith().topic("topic/subtopic").payload("payload".getBytes()).qos(pubQoS).send();
System.out.println("Published message");
  • A client subscribing with QoS 1 and using manual acknowledgment.
Mqtt5ClientBuilder mqttClientBuilder = MqttClient.builder()
                                                 .identifier("client-subscriber")
                                                 .serverHost("localhost")
                                                 .serverPort(1883)
                                                 .useMqttVersion5();
Mqtt5RxClient mqttClient = mqttClientBuilder.buildRx();

mqttClient.connect(Mqtt5Connect.builder().build()).blockingGet();
System.out.println("Connected to MQTT Broker");

mqttClient.toAsync()
          .subscribeWith()
          .topicFilter("topic/#")
          .qos(MqttQos.AT_LEAST_ONCE)
          .callback((Mqtt5Publish mqtt5Publish) -> {
              System.out.println("Received message: "
                      + new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8));

              mqtt5Publish.acknowledge();
              mqttClient.toBlocking().unsubscribeWith().topicFilter("topic/#").send();
              mqttClient.toBlocking().disconnectWith().send();

              System.out.println("Exit subscriber");
          })
        .manualAcknowledgement(true)
          .send()
          .get();

System.out.println("Subscribed to MQTT Broker");

Upon receiving the subscription, the client acknowledges the message, unsubscribes and disconnects from the broker, but we notice that this client doesn't exit as expected in this scenario.

The main function executes to the end. The unsubscribe and disconnect method calls on the client succeed. But the whole Java application doesn't exit. In the debugger, there can be seen still some running threads.

For comparison, the following cases were checked, alternating between using manual ack or not and publishing with different QoS.

  • Case 1: no manual ack, publish with QoS 1 => subscribing client exits
  • Case 2: no manual ack, publish with QoS 0 => subscribing client exits
  • Case 3: use manual ack, publish with QoS 1 => subscribing client exits
  • Case 4: use manual ack, publish with QoS 0 => subscribing client doesn't exit

Why doesn't the client exit in Case 4? Is it an error to manually ack a message published with QoS 0? We also tried to not ack the message, but the application still doesn't quit.

We also considered another case, where we declare manual ack on the subscription, but don't actually ack the receeived message:

  • Case 5: declare manual ack, don't ack message, publish with QoS 1 => subscribing client doesn't exit

What is the problem in Case 5? Is it because we don't manually ack a message published with QoS 1? Although we don't explicitly ack the QoS 1 message, we successfully call unsubscribe and disconnect on the client, so we would expect the client to quit gracefully.

Thank you!

@SgtSilvio
Copy link
Member

SgtSilvio commented Feb 14, 2021

Hi @evisa-lumani
Sorry for the delayed response.
Case 4 seems like a bug. We will investigate and fix this.
Regarding your code example: you block inside the callback of the async API. Although this may work, it is not supported.
Regarding case 5: you are required to acknowledge every message when using manual acknowledgement. You can do this also after disconnecting the client.

@SgtSilvio
Copy link
Member

Hi @evisa-lumani
Case 4 is now fixed and will be released with version 1.2.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants