Skip to content

Possible Windows memory leak in btleplug 0.13.1 #476

Description

@Raphiiko

Describe the bug

Hi, I recently migrated my application OyasumiVR from bluest to btleplug. Since then, I've had reports of memory usage climbing over time on Windows, which I've also reproduced myself with btleplug 0.13.1.

I want to be upfront that this isn't my area of expertise, so I threw Astra at the problem. It came up with a possible cause and patch. I can personally only speak for the before and after results, not the findings or solution, but I figured I'd report it anyway.

Expected behavior

btleplug should release resources when they're no longer needed, without memory accumulating over repeated use.

Actual behavior

I ran the unpatched 0.13.1 build for about eight hours, then the patched build for two hours, with the same five Bluetooth LE devices connected.

Unpatched 0.13.1 With the proposed patch
Duration About 8 hours 2 hours
Private memory at start 53 MiB 53 MiB
Private memory at end 1,477 MiB 56 MiB
Memory growth over matching periods About 182 MiB/hour About 0.37 MiB/hour

Astra calculated the growth rates from the matching first two hours, excluding the first ten minutes. Memory kept growing throughout the unpatched run. With the patch, it stayed below 57 MiB.

All five devices connected in both runs. Neither run logged connection failures during measurement. I haven't tested the patched build for the full eight hours.

Additional context

Setup

  • Windows
  • Intel Wireless Bluetooth, driver 24.30.1.1
  • btleplug 0.13.1
  • Five Bluetooth LE devices

Dump analysis

Astra analyzed memory dumps from both runs using their matching executables and PDBs. It identified the following radio callbacks:

Near the start At the end
Unpatched 18 3,198
Patched 1 1

In the unpatched final dump, it traced those callbacks to 3,198 adapter managers and about 73,000 retained device objects. Those are accumulated objects from repeated discovery, not separate physical devices. Their map storage alone accounted for about 1.17 GiB.

According to its analysis, 3,197 of those managers had only one remaining strong reference, held by a radio callback. It also checked a sample of the callback and manager allocations against Windows heap records.

Suspected cause

Astra's explanation is that the Windows Radio::StateChanged handler remains registered after its adapter is dropped. The callback holds references to the radio and device manager, keeping the manager's device data alive.

The dump findings appear to support that explanation, but I haven't independently verified Astra's interpretation.

Proposed patch

This PR contains the patch Astra implemented for 0.13.1. It removes the radio handler when the last adapter clone is dropped and changes the callback to hold a weak reference to the manager.

The scan-handler cleanup already present in 0.13.1 is unchanged.

I can't vouch for the implementation or whether this is the correct fix. I can only confirm that memory consumption was much lower in my test with it applied. I'd appreciate someone familiar with the Windows implementation taking a look.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions