Skip to content

Memory leak when receiving duplicate device responses #201

@mstovenour

Description

@mstovenour

I've been working on a thorough solution for #114. In the process I discovered that duplicate device responses all end up queued in Device._directACK_received_queue but only one message is removed from the queue by Device._wait_for_direct_ACK(). The way the code operates the Device._directACK_received_queue should never have more that one message in it. Yet that queue grows over time with every duplicate message received. It also means that each time Device._wait_for_direct_ACK() runs, it pulls old, duplicate messages out of the queue. This was my issue. However this is a long term problem for anyone because the message queue for each device will grow unbounded if the system runs for a long time. My home is large and I have 20 devices so I get a few duplicate messages for the devices that are further away from the PLM.

I think this is relatively easy to fix by beefing up Device._is_duplicate() however when I look at that function I can't really understand the motivation behind its implementation. A beefier solution is to directly compare each component of the saved messages (target, flags, cmd1, cmd2, extended data) while ignoring the hop counts (lower nibble of flags) when deciding if the current message is a duplicate. I'm concerned about changing that method though because I don't really understand why it only compares cmd1 and group and why it only works for ALL-LinkCleanup and ALL-LinkBroadcast messages. @teharris1 could you help me understand the motivation?

Below is more proof of the issue:
I added a bit of extra logging in the process of understanding why my messages were not being processed correctly. You can checkout the fix_issue_201 branch in my repository to run this locally. I use the interactive tool and run the on_off_test or newly added test_device function. I run it multiple times until I see the log Got Direct ACK message. Already in queue: 1 or any number > 0. I also added logging for the message object IDs so it is easier to track which message instance is being processed out of the queue. Below is an edited logging output. I removed a lot of the irrelevant lines so it would be easier to see the actual message queuing.

`INFO:insteonplm.tools:Send on request
INFO:insteonplm.tools:----------------------
DEBUG:insteonplm.devices:Starting 35.3E.ED Device._send_msg: Queuing message
DEBUG:insteonplm.plm:TX: 3059110124:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0xNone}
DEBUG:insteonplm.plm:RX: 3059071596:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0x06}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Message ACK 3059071596
DEBUG:insteonplm.plm:RX: 3059071372:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x11, 'cmd2': 0xff}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Direct ACK message. Already in queue: 0, Queueing 3059071372:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x11, 'cmd2': 0xff}
DEBUG:insteonplm.plm:Processing _acknak_queue acknak: 3059071596:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0x06} msg: 3059110124:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0xNone}
DEBUG:insteonplm.plm:ACK or NAK received
DEBUG:insteonplm.devices:Starting Device._wait_for_direct_ACK
DEBUG:insteonplm.devices:Remaining queue 0, Direct ACK: 3059071372:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x11, 'cmd2': 0xff}
INFO:insteonplm.tools:Device 35.3E.ED state 0x1 value is changed to 255

INFO:insteonplm.tools:Send off request
INFO:insteonplm.tools:----------------------
DEBUG:insteonplm.devices:Starting 35.3E.ED Device._send_msg: Queuing message
DEBUG:insteonplm.plm:TX: 3059119819:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0xNone}
DEBUG:insteonplm.plm:RX: 3059107180:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0x06}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Message ACK 3059107180
DEBUG:insteonplm.devices:Look for direct ACK
DEBUG:insteonplm.plm:RX: 3059168559:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Direct ACK message. Already in queue: 0, Queueing 3059168559:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
DEBUG:insteonplm.plm:RX: 3059097356:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Direct ACK message. Already in queue: 1, Queueing 3059097356:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
DEBUG:insteonplm.plm:Processing _acknak_queue acknak: 3059107180:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0x06} msg: 3059119819:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0xNone}
DEBUG:insteonplm.plm:ACK or NAK received
DEBUG:insteonplm.devices:Starting Device._wait_for_direct_ACK
DEBUG:insteonplm.devices:Remaining queue 1, Direct ACK: 3059168559:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
INFO:insteonplm.tools:Device 35.3E.ED state 0x1 value is changed to 0

INFO:insteonplm.tools:Send on request
INFO:insteonplm.tools:----------------------
DEBUG:insteonplm.devices:Starting 35.3E.ED Device._send_msg: Queuing message
DEBUG:insteonplm.plm:TX: 3059085868:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0xNone}
DEBUG:insteonplm.plm:RX: 3059069420:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0x06}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Message ACK 3059069420
DEBUG:insteonplm.devices:Look for direct ACK
DEBUG:insteonplm.plm:RX: 3059069100:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x11, 'cmd2': 0xff}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Direct ACK message. Already in queue: 1, Queueing 3059069100:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x11, 'cmd2': 0xff}
DEBUG:insteonplm.plm:Processing _acknak_queue acknak: 3059069420:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0x06} msg: 3059085868:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x11, 'cmd2': 0xff, 'acknak': 0xNone}
DEBUG:insteonplm.plm:ACK or NAK received
DEBUG:insteonplm.devices:Starting Device._wait_for_direct_ACK
DEBUG:insteonplm.devices:Remaining queue 1, Direct ACK: 3059097356:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
INFO:insteonplm.tools:Device 35.3E.ED state 0x1 value is changed to 255

INFO:insteonplm.tools:Send off request
INFO:insteonplm.tools:----------------------
DEBUG:insteonplm.devices:Starting 35.3E.ED Device._send_msg: Queuing message
DEBUG:insteonplm.plm:TX: 3059118561:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0xNone}
DEBUG:insteonplm.plm:RX: 3059071500:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0x06}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Message ACK 3059071500
DEBUG:insteonplm.devices:Look for direct ACK
DEBUG:insteonplm.plm:RX: 3059106757:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
DEBUG:insteonplm.devices:Starting Device.receive_message for 35.3E.ED
DEBUG:insteonplm.devices:Got Direct ACK message. Already in queue: 1, Queueing 3059106757:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x13, 'cmd2': 0x00}
DEBUG:insteonplm.plm:Processing _acknak_queue acknak: 3059071500:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0x06} msg: 3059118561:{'code': 0x62, 'address': 35.3E.ED, 'flags': 0x00, 'cmd1': 0x13, 'cmd2': 0x00, 'acknak': 0xNone}
DEBUG:insteonplm.plm:ACK or NAK received
DEBUG:insteonplm.devices:Starting Device._wait_for_direct_ACK
DEBUG:insteonplm.devices:Remaining queue 1, Direct ACK: 3059069100:{'code': 0x50, 'address': 35.3E.ED, 'target': 1E.DC.30, 'flags': 0x20, 'cmd1': 0x11, 'cmd2': 0xff}
INFO:insteonplm.tools:Device 35.3E.ED state 0x1 value is changed to 0
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions