From 5440b79252545eed286cf34e7ce5a30ac9666e12 Mon Sep 17 00:00:00 2001 From: Alexis Couvreur Date: Tue, 19 May 2026 23:00:47 -0400 Subject: [PATCH] fix(windows): close leaked resources A lot of resources were not closed. Closes #451 --- gap_windows.go | 38 +++++++++++++++++++++++++------------- gattc_windows.go | 17 +++++++++++++++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/gap_windows.go b/gap_windows.go index 8f108081..92b60c87 100644 --- a/gap_windows.go +++ b/gap_windows.go @@ -233,27 +233,36 @@ func getScanResultFromArgs(args *advertisement.BluetoothLEAdvertisementReceivedE var manufacturerData []ManufacturerDataElement var serviceUUIDs []UUID - if winAdv, err := args.GetAdvertisement(); err == nil && winAdv != nil { - // Extract manufacturer data - vector, _ := winAdv.GetManufacturerData() - size, _ := vector.GetSize() + + // Extract manufacturer data + manDataVector, _ := winAdv.GetManufacturerData() + if manDataVector != nil { + defer manDataVector.Release() + size, _ := manDataVector.GetSize() for i := uint32(0); i < size; i++ { - element, _ := vector.GetAt(i) + element, _ := manDataVector.GetAt(i) manData := (*advertisement.BluetoothLEManufacturerData)(element) companyID, _ := manData.GetCompanyId() buffer, _ := manData.GetData() - manufacturerData = append(manufacturerData, ManufacturerDataElement{ - CompanyID: companyID, - Data: bufferToSlice(buffer), - }) + if buffer != nil { + manufacturerData = append(manufacturerData, ManufacturerDataElement{ + CompanyID: companyID, + Data: bufferToSlice(buffer), + }) + buffer.Release() + } + manData.Release() } + } - // Extract service UUIDs - vector, _ = winAdv.GetServiceUuids() - size, _ = vector.GetSize() + // Extract service UUIDs + serviceUuidsVector, _ := winAdv.GetServiceUuids() + if serviceUuidsVector != nil { + defer serviceUuidsVector.Release() + size, _ := serviceUuidsVector.GetSize() for i := uint32(0); i < size; i++ { - element, _ := vector.GetAt(i) + element, _ := serviceUuidsVector.GetAt(i) // element is not a pointer, but a GUID struct. But we cannot convert // unsafe.Pointer to a non-pointer type, so instead we are doing this: serviceGUID := (*syscall.GUID)(unsafe.Pointer(&element)) @@ -342,6 +351,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err if err != nil { return Device{}, err } + defer bleDeviceOp.Release() // We need to pass the signature of the parameter returned by the async operation: // IAsyncOperation @@ -367,6 +377,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err if err != nil { return Device{}, err } + defer dID.Release() // Windows does not support explicitly connecting to a device. // Instead it has the concept of a GATT session that is owned @@ -375,6 +386,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err if err != nil { return Device{}, err } + defer gattSessionOp.Release() if err := awaitAsyncOperation(gattSessionOp, genericattributeprofile.SignatureGattSession); err != nil { return Device{}, fmt.Errorf("error getting gatt session: %w", err) diff --git a/gattc_windows.go b/gattc_windows.go index c4b01aa8..67c7bbe3 100644 --- a/gattc_windows.go +++ b/gattc_windows.go @@ -53,6 +53,7 @@ func (d Device) DiscoverServices(filterUUIDs []UUID) ([]DeviceService, error) { if err != nil { return nil, err } + defer getServicesOperation.Release() if err := awaitAsyncOperation(getServicesOperation, genericattributeprofile.SignatureGattDeviceServicesResult); err != nil { return nil, err @@ -64,6 +65,7 @@ func (d Device) DiscoverServices(filterUUIDs []UUID) ([]DeviceService, error) { } servicesResult := (*genericattributeprofile.GattDeviceServicesResult)(res) + defer servicesResult.Release() status, err := servicesResult.GetStatus() if err != nil { @@ -77,6 +79,7 @@ func (d Device) DiscoverServices(filterUUIDs []UUID) ([]DeviceService, error) { if err != nil { return nil, err } + defer servicesVector.Release() // Convert services vector to array servicesSize, err := servicesVector.GetSize() @@ -197,6 +200,7 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar if err != nil { return nil, err } + defer getCharacteristicsOp.Release() // IAsyncOperation if err := awaitAsyncOperation(getCharacteristicsOp, genericattributeprofile.SignatureGattCharacteristicsResult); err != nil { @@ -209,12 +213,14 @@ func (s DeviceService) DiscoverCharacteristics(filterUUIDs []UUID) ([]DeviceChar } gattCharResult := (*genericattributeprofile.GattCharacteristicsResult)(res) + defer gattCharResult.Release() // IVectorView charVector, err := gattCharResult.GetCharacteristics() if err != nil { return nil, err } + defer charVector.Release() // Convert characteristics vector to array characteristicsSize, err := charVector.GetSize() @@ -361,9 +367,14 @@ func (c DeviceCharacteristic) write(p []byte, mode genericattributeprofile.GattW if err != nil { return 0, err } + defer value.Release() // IAsyncOperation asyncOp, err := c.characteristic.WriteValueWithOptionAsync(value, mode) + if err != nil { + return 0, err + } + defer asyncOp.Release() if err := awaitAsyncOperation(asyncOp, genericattributeprofile.SignatureGattCommunicationStatus); err != nil { return 0, err @@ -395,6 +406,7 @@ func (c DeviceCharacteristic) Read(data []byte) (int, error) { if err != nil { return 0, err } + defer readOp.Release() // IAsyncOperation if err := awaitAsyncOperation(readOp, genericattributeprofile.SignatureGattReadResult); err != nil { @@ -407,16 +419,19 @@ func (c DeviceCharacteristic) Read(data []byte) (int, error) { } result := (*genericattributeprofile.GattReadResult)(res) + defer result.Release() buffer, err := result.GetValue() if err != nil { return 0, err } + defer buffer.Release() datareader, err := streams.DataReaderFromBuffer(buffer) if err != nil { return 0, err } + defer datareader.Release() bufferlen, err := buffer.GetLength() if err != nil { @@ -496,6 +511,7 @@ func (c DeviceCharacteristic) EnableNotificationsWithMode(mode NotificationMode, if err != nil { return } + defer buf.Release() reader, err := streams.DataReaderFromBuffer(buf) if err != nil { @@ -527,6 +543,7 @@ func (c DeviceCharacteristic) EnableNotificationsWithMode(mode NotificationMode, if err != nil { return err } + defer writeOp.Release() // IAsyncOperation if err := awaitAsyncOperation(writeOp, genericattributeprofile.SignatureGattCommunicationStatus); err != nil {