Closed westbywest closed 10 months ago
@westbywest Hi, I can't reproduce it. I use the same code. After restarting the mqtt service. It can still be reconnected normally.
Hi Ben,
Thanks for the minimal example, I can reproduce it on my side 👍 Moving the client
statement inside the while loop is a good option in the meantime, but we do want it to work like in the example (without re-initializing the client instance), so it seems there's something broken, good catch!
For reference, we want the client to be reusable, but not reentrant, the corresponding PR is #216 (by @vvanglro, thanks again! 🚀).
This is an interesting one! I tested this a bit more thouroughly with a local Docker mosquitto broker that I shut down. With some logging on the exact exception types and on the relevant lock, this gives:
lock acquired
lock released
<class 'aiomqtt.error.MqttCodeError'>
ERROR: [code:7] The connection was lost.; Reconnecting in 5 seconds ...
lock acquired
<class 'aiomqtt.error.MqttError'>
ERROR: [Errno 61] Connection refused; Reconnecting in 5 seconds ...
<class 'aiomqtt.error.MqttReentrantError'>
ERROR: Does not support reentrant; Reconnecting in 5 seconds ...
What we see here is that the lock is released when an MqttCodeError
is raised, but not when an MqttError
is raised. Due to the lock not being correctly released, the code runs into this condition inside __aenter__
and raises the "Does not support reentrant" error that you see.
If I got it right the reason for the lock not being released is that the code already fails inside __aenter__
after aquiring the lock and inside the call to connect()
. Due to this failure __aexit__
(where the lock is released) is not called.
@vvanglro, are you able to reproduce the error with this extra information?
I just pushed a script to spin up a local Mosquitto broker via Docker to make it easier to reproduce these steps. After calling the script you should be able to connect to the broker via aiomqtt.Client("localhost", port=1883)
🙂
The emqx image I use. Maybe we should catch the exception of connect method and release the lock.
Sounds good, do you want to make a PR with a fix and a test? 💯
Sounds good, do you want to make a PR with a fix and a test? 💯
next monday i'll take the time to do it.
Great job to both of you (@vvanglro and @empicano) with this quick fix on this issue. :smile: :+1:
Hello, and thank you for the great library. Can you consider tagging a release with the fix?
I am running into this exact issue (the Lock
not being released appropriately) and it would be really nice to avoid running the main
code long term.
Done 🙂 Happy to hear that you like aiomqtt!
Adapting the reconnection example to throw exceptions verbosely:
Subsequent reconnection attempts actually will always fail on "Does not support reentrant," even if the target host becomes available.
For reconnection to succeed, I have to move
client = ...
statement to within the while loop. Is this intended usage, and the example happens to be incorrect?Observed under python 3.10.7, asyncio 3.4.3, aiomqtt 1.1.0.