mosquitto重连失败问题排查
在使用mosquitto做客户端连接时,重连机制:
1. 封装的MqttClient类,包含一个mosquittopp类实例。
2.MqttClient的start线程会启动一个常驻线程,线程中初始化mosquittopp类实例,并建立连接。
2.1 建立连接的过程是,先调用mosquitto_connect,成功后调用mosquitto_loop_start开启一个loop。
2.2 线程中mosquittopp连接成功后,会阻塞等待,直到mosquittopp发生断连
2.3 mosquittopp发生断连后,进入下一次循环,重新建立连接。
3.mosquittopp实例断连,会在on_disconnect回调中触发条件变量,解除2.1中的阻塞,进入连接重建。
4.主动disconnect接口会调mosquitto_disconnect,然后调用mosquitto_loop_stop。
原来的流程,是断连后,会遇到的问题:会发生崩溃或者卡死的问题。
经过调查,发现其现象原因是,在发生断连后,回调on_disconnect中只只调用了mosquitto_loop_stop,而且非强制,所以loop线程并没有真正结束,mosquitto_loop_stop也会阻塞在join中。
然后当网络恢复,此时loop线程会重新连接,但是此时外部的stop消息(sockpairR)会被读到,mosquittopp类线程退出,实例销毁。这个过程是未知的,可能会导致空指针或者非预期内的状态。导致崩溃。
我们查看mosquitto的接口说明:
里面提到,在调用mosquitto_loop_stop之前要调用mosquitto_disconnect(尽管此时已经由于网络断连,on_disconnect被调用)。查看mosquitto_disconnect函数,其中会设置连接状态为mosq_cs_disconnected。
这样可以防止外部在销毁实例的时候,实例内部还在进行connect操作,保障线程尽快结束。
所以最终,在on_disconnect中,先调用mosquitto_disconnect之后,再调用mosquitto_loop_stop。整个重连处理的逻辑得以运转完善,问题解决。