paho.mqtt.python
paho.mqtt.python copied to clipboard
State of client doesn't change to disconnected after connection lost
When not using loop_forever or loop_start and running the loop in the main thread, a hard disconnect gets captured by the client but doesn't change the output of is_connected() method.
Steps to reproduce:
- Run an mqtt server, I use emqx:
docker run -d --name emqx -p 18083:18083 -p 1883:1883 emqx/emqx:v4.0.0
- Run the code below:
import time
import logging
import paho.mqtt.client as mqtt
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
def on_connect(client, userdata, flags, rc):
logger.debug('Connected with result code ' + str(rc))
# subscribe
client.subscribe('tienda/#')
def on_message(client, userdata, msg):
logger.debug(msg.topic + " " + str(msg.payload))
# if b'stop' in msg.payload:
# client.disconnect()
def on_disconnect(client, flags, rc):
logger.debug('Disconnected with result code ' + str(rc))
# client.reconnect()
# Build the client
client = mqtt.Client(clean_session=True)
logger.error('Client initialized with status: %s', client._state)
# Specify callback function
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.enable_logger(logger)
# client.username_pw_set('topse', 'cret')
# Establish a connection
client.connect('localhost', 1883, 60)
# wait for connection
while not client.is_connected():
logger.debug('Connecting')
client.loop(timeout=1)
logger.debug('Connected')
# This loops never ends even after there is no connection at all
while client.is_connected():
client.loop()
time.sleep(1)
logger.debug('In main loop: %s', client.is_connected())
- browse http://localhost:18083/#/clients and find you client and disconnect it.
The result is that you will see the Disconnected with result code: 0 message, but the program never exits and keeps printing:
DEBUG:__main__:In main loop: True
DEBUG:__main__:In main loop: True
DEBUG:__main__:In main loop: True
DEBUG:__main__:In main loop: True
DEBUG:__main__:In main loop: True
The problem is the internal field _state doesn't changes to disconnected or any other states when we are not calling the disconnect method directly. This causes the is_connected() method return true and the loop never exits.
paho-mqtt version: 1.5.1
Running the loop just like loop_forever() has no problem:
while True:
rc = 0
while rc == 0:
logger.debug(client._state)
rc = client.loop()
time.sleep(2)
try:
client.reconnect()
except (socket.error, OSError, WebsocketConnectionError):
logger.error("Connection failed, retrying")
The problem is that is_connected() returns wrong result.
Possibly related to #441.
I'm able to reproduce this with the sample code your provided and killing the broken after log of In main loop.
I've used Mosquitto rather than emqx but this shouldn't matter.
#795 fix the issue in my test scenario.