BUG: Messages is sent twice
ThomasTJdev opened this issue · comments
During the implementation of PR #9 , the subscribe()
failed when using asyncCheck
. Debugging the packages on the broker and using -d:dev
on nmqtt shows, that the packages are sent twice (2).
To make a quick workaround, the commit 62e5d8f checks, that the SUBACK
package received matches the msgId
in the queue - due to deletion of the first send message, which would crash the program when trying to delete the same package again.
The problem is also shown on the publish
- which might could be part of issue #7?
Subscribe
Broker
1584256896: Sending CONNACK to hallo (0, 0)
1584256897: Received PINGREQ from hallo
1584256897: Sending PINGRESP to hallo
1584256897: Received SUBSCRIBE from hallo # => HERE
1584256897: # (QoS 2)
1584256897: Sending SUBACK to hallo # => Package received, and msgId removed
1584256897: Received SUBSCRIBE from hallo # => HERE
1584256897: # (QoS 2)
1584256897: Sending SUBACK to hallo # => Crash due to msgId already deleted
1584256898: Received PINGREQ from hallo
1584256898: Sending PINGRESP to hallo
1584256899: Received PINGREQ from hallo
Client
tx> Subscribe(02): 00 01 00 01 23 02
tx> Subscribe(02): 00 01 00 01 23 02
rx> PingResp(00):
rx> SubAck(00): 00 01 02 # => HERE
rx> SubAck(00): 00 01 02 # => HERE
tx> PingReq(00):
rx> PingResp(00):
tx> PingReq(00):
Publish
Broker
1584257384: Received PUBLISH from hallo (d0, q2, r0, m1, 'test1', ... (5 bytes))
1584257384: Sending PUBREC to hallo (m1, rc0)
1584257384: Received PUBLISH from hallo (d0, q2, r0, m1, 'test1', ... (5 bytes))
1584257384: Sending PUBREC to hallo (m1, rc0)
1584257384: Received PUBREL from hallo (Mid: 1)
1584257384: Sending PUBCOMP to hallo (m1)
1584257384: Received PUBREL from hallo (Mid: 1)
1584257384: Sending PUBCOMP to hallo (m1)
Client
tx> Publish(04): 00 05 74 65 73 74 31 00 01 68 61 6C 6C 6F
tx> Publish(04): 00 05 74 65 73 74 31 00 01 68 61 6C 6C 6F
rx> PingResp(00):
rx> PubRec(00): 00 01
tx> PubRel(02): 00 01
rx> PubRec(00): 00 01
tx> PubRel(02): 00 01
rx> PubComp(00): 00 01
rx> PubComp(00): 00 01
Using asyncCheck
instead of await
in send()
eliminates the double sending.
asyncCheck ctx.s.send(hdr[0].unsafeAddr, hdr.len)
if len > 0:
asyncCheck ctx.s.send(pkt.data[0].unsafeAddr, len)
My guess is that work()
messes up its bookkeeping because it can be scheduled on async work while it is called again (for example, from the ping async proc) , and its current design is not safe for reentrancy.
This should be the simple fix for that: https://github.com/zevv/nmqtt/pull/new/zevv-inwork, making it safe to call work()
My guess is that
work()
messes up its bookkeeping because it can be scheduled on async work while it is called again (for example, from the ping async proc) , and its current design is not safe for reentrancy.This should be the simple fix for that: https://github.com/zevv/nmqtt/pull/new/zevv-inwork, making it safe to call work()
That's a good solution.
Closing in relation to #13