eclipse-paho / eclipse-paho/paho.mqtt.java

Sometimes a 'deadlock' may occur when resubscribing to a topic in the connectComplete callback

Open
#999 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
2.3k
Forks
919
PR merge metrics
No merged PRs in 30d

Description

- [x] Bug exists Release Version 1.2.5 ( Master Branch)
- [x] Bug exists in MQTTv3 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)
- [ ] Bug exists in MQTTv5 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)

## Reproduction steps
1. create a sub client(subscribing to a topic in the connectComplete callback)
`public void connectComplete(boolean reconnect, String serverURI) {
myClient.subscribe(this.topic);
}
`
and create a pub client
3. the pub client continuously publishes messages.
4. the sub client receive messages
5. then, close the sub client whille the pub client continues to publish message, ensuring that the pub client still published more than 10 message
6. now, the sub client session(in broker) has more than 10 unconsumed messages
7. close the pub client, reconnect the sub client(sub client id must unchanged)
8. finally, the sub client will be blocked until the `checkForActivity` method closes the client
```
���� 11, 2023 5:22:46 ���� org.eclipse.paho.client.mqttv3.internal.ClientState checkForActivity
����: client1: Timed out as no activity, keepAlive=15,000,000,000 lastOutboundActivity=202,748,527,866,900 lastInboundActivity=202,733,513,164,800 time=202,763,529,941,000 lastPing=202,748,527,900,000
on connectionLost
```

## More Information
1. the `checkForActivity` Method closes the client because that client was not received MqttPingResp(ping response)
2. additionally, I've discovered that subscribe ack(MqttSuback) was not recevied either
3. however, ping ack and sub ack both had been sent by the broker(EMQX Broker)

![image](https://github.com/eclipse/paho.mqtt.java/assets/39401478/eb27b83f-5f02-4242-94f6-54f20b9ea0e8)
![image](https://github.com/eclipse/paho.mqtt.java/assets/39401478/57c07cc1-27b0-43e7-8ebb-bd7fdb6ccabd)

4. the sub client can recevied 10 message from broker when reconnecting(debug can found it, but did not send message ack)

## Based on further speculation
- the sub client hadn't received ping ack and sub ack
- the status of the Rec Thread(CommsReceiver) may be in WAITING state

## Reason analysis
### Paho Mqtt Thread
- CommsReceiver(receive message from broker)
- CommsCallback(consume message)
- CommsSender(publish meesage)

### Client startup process (coarse-grained):
1. connect packet sent
2. connect ack recevied
3. received message from broker if need
4. the `connectComplete` called
5. subscribe a topic in the `connectComplete`, and then the CallThread(CommsCallback) will wait until it gets sub ack notified

### Rec Thread(CommsReceiver) Part
1. connect ack received
2. received message from broker(more than 10 messages)
3. put the messages in the `CommsCallback.messageQueue`

![image](https://github.com/eclipse/paho.mqtt.java/assets/39401478/f073f2da-24ec-4fb3-9160-d9f7a319a867)

5. The important logic is coming:`clientState.notifyReceivedMsg(message)`
**Rec Thread(CommsReceiver) will wait when ` messageQueue.size()` >= 10**

![image](https://github.com/eclipse/paho.mqtt.java/assets/39401478/9b7f2a91-3e7e-4e6c-a71b-bea0e924eb4c)

## Conclusion

**1. The Call Thread(CommsCallback) state in WAITING when subscribe in the `connectComplete `
2. The Rec Thread(CommsReceiver) state in WAITING when `CommsCallback.messageQueue` size >= 10
3. The `CommsCallback.messageQueue` consumed in Call Thread(CommsCallback), but Call Thread(CommsCallback) state in WAITING now
4. The Rec Thread(CommsReceiver) state in WAITING, Thus Ping Ack and Sub Ack are never received.
5. Based on the above point, The Call Thread(CommsCallback) will not be notified
6. Finally, The `PingTask` will close the client**

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.