Closed mmattel closed 9 months ago
I have come across a similar scenario and I think I have figured it out. My SIGINT handler was gracefully calling mqttclient.disconnect()
— maybe yours was too? — and I observed that the Last Will message was not being published. It turns out that this is the expected behaviour. The MQTT protocol makes a distinction between graceful and ungraceful disconnects (ref) and defines that the Last Will only applies to ungraceful disconnects, for example a dropped network connection, device power loss, or the client process being suddenly killed by the OS (e.g. kill -9 $PID
on a Linux prompt). When you say that a CTRL-C message gets printed to the console, I imagine that this means that your shell/OS forcibly kills the process, simulating an ungraceful disconnect.
I think it makes sense for a SIGINT handler to gracefully terminate the client including a disconnect()
call, but in this case the Last Will message will not be automatically published, by design. What I have done is to explicitly publish the same message as the Last Will through a regular publish()
call, just before the disconnect()
call in the signal handler. Et voilà!
Thanks for the explanation, this guided me into the right direction, but it was not complete. When initiating a publish and disconnect right afterwards, the message will not be sent as disconnect is faster than publishing. You need to wait until it was published, then you can disconnect. Here is the code I am using now successfully.
def graceful_shutdown():
print()
# the will_set is not sent on graceful shutdown by design
# we need to wait until the message has been sent, else it will not appear in the broker
publish_result = mqttclient.publish(mqtt_state_topic, payload = "offline", qos = mqtt_qos, retain = True)
publish_result.wait_for_publish()
mqttclient.disconnect()
mqttclient.loop_stop()
sys.exit()
# catch ctrl-c
def signal_handler(signum, frame):
graceful_shutdown()
signal.signal(signal.SIGINT, signal_handler)
I'm going to close this because it looks like you arrived at a pretty decent answer yourself! Please feel free to reopen if more info is needed (we are trying to get on top of the issues!).
Note: This is part of an exercise to clean up old issues so that the project can move forwards. Due to the number of issues being worked through mistakes will be made; please feel free to reopen this issue (or comment) if you believe it's been closed in error.
I am desperately looking for a hint how to properly implement a
keyboard interrupt
(ctrl-c) in a way thaton_connect
andlast_will
will get respected. I searched a lot but have not found any hint.At the moment using the code below, whenever I press ctrl-c, the program exits correctly and
will_set
is respected - but you get a ctrl-c message printed on the console.Adapting the code by adding a signal handler or a try/except in the while loop, pressing ctrl-c does not print the exit message, but
will_set
gets not respected.Tips and hints how to solve this are welcomed.