locked
Program crashed after recived Bluetooth LE Notification RRS feed

  • Question

  • I have my own BLE Driver class written in C++ by using Win32API(bluetoothleapis) for Win10 Desktop environment. And It worked fine before.

    And today, I don't even know window updated or what, I haven't edit my code and run without rebuild it and it crash.

    It keep saying "visual studio has triggered a breakpoint".

    Tracing ended with programs without source code, after disassembling find that program stop in _UnhandledExceptionFilter, which caused by BthleGattEventingIOThreadProc.

    After testing, I found that It'll only crash after received BLE Characteristic Notification and entered User Defined Callback function ( no matter it's empty or not).

    Here is screenshot

    Hope it caused by Windows update and can be fixed as soon as possible.......(May be KB3156421?)

    Thanks for any help!

    Platform:

    OS:Windows 10 Student edition x64

    CPU:E3 1230 V3

    Bluetooth Dongle : Intel AC 8260

    • Edited by Sky Wolfs Saturday, May 14, 2016 4:44 PM Add HW information
    Saturday, May 14, 2016 3:46 PM

Answers

  • This issue only happens when running code using the Win32 Bluetooth APIs compiled for x86 architecture. There are no issues when using the same API compiled for AMD64 architecture. The WinRT APIs are not impacted across any architecture and we strongly recommend developers to use the Bluetooth WinRT APIs instead of the Win32 ones: https://msdn.microsoft.com/en-us/windows.devices.bluetooth.genericattributeprofile

    It has to do with the callback using a mismatched calling convention in Visual Studio by default, which x86 architecture are very sensitive about. This issue existed previously but only visibly manifested recently due to the KB3156421. To workaround this issue on x86 architecture and avoid leaking memory, please add CALLBACK before the declaration/definition of your callback routine. Then, make sure to c-cast (or reinterpret_cast) the callback function into PFNBLUETOOTH_GATT_EVENT_CALLBACK when giving it as parameter to BluetoothGATTRegisterEvent.

    Example:

    void CALLBACK HeartRateMeasurementEvent(
        _In_ BTH_LE_GATT_EVENT_TYPE EventType,
        _In_ PVOID EventOutParameter,
        _In_opt_ PVOID Context);
    
    ...
    
    hr = BluetoothGATTRegisterEvent(
            handle,
            CharacteristicValueChangedEvent,
            (PVOID)&registration,
            (PFNBLUETOOTH_GATT_EVENT_CALLBACK)HeartRateMeasurementEvent,
            NULL,
            &eventHandle,
            BLUETOOTH_GATT_FLAG_NONE);


    Friday, May 27, 2016 6:20 PM

All replies

  • Okay....It caused by KB3156421.

    After uninstalling it, work normally now.

    Where should I report this issue to MS?

    And should I close this thread?


    • Marked as answer by Sky Wolfs Sunday, May 15, 2016 6:10 AM
    • Edited by Sky Wolfs Monday, May 16, 2016 10:50 AM
    • Unmarked as answer by Sky Wolfs Saturday, May 28, 2016 3:53 AM
    Saturday, May 14, 2016 5:31 PM
  • Thank-you for posting this!  I  have been fighting with this for several hours, but my code is brand new, so I never would have thought a recent MS update would be the cause.  Uninstalling KB3156421 seemed to correct for me, as well.
    Sunday, May 15, 2016 4:40 AM
  • Hi,

    +1 to this! And I also uninstalled KB3156421 and it solved the problem. However, this must be fixed as soon as possible by Microsoft, or else at least publish a workaround.


    Monday, May 16, 2016 1:52 PM
  • Thanks for reporting this problem.  The bluetooth team is investigating.
    Tuesday, May 17, 2016 6:30 PM
  • I've had the exact same problem since this update. In my case it only happens when compiling for 32-bit. 64-bit still works fine for some reason. Can anyone else try it at 64-bit and verify?
    Thursday, May 19, 2016 7:53 AM
  • I've had the exact same problem since this update. In my case it only happens when compiling for 32-bit. 64-bit still works fine for some reason. Can anyone else try it at 64-bit and verify?

    Hi,

    It work on X64 platform, but I don't know it's my device's or windows'  problem, feeling a little lag when receiving notification?

    Saturday, May 21, 2016 5:53 AM
  • Sorry for the late response, I didn't notice any lag but I wasn't looking for specifically. I will try to test it later.
    Tuesday, May 24, 2016 12:46 PM
  • Same issue here. One callback of the notification worked and then the application crashes.

    windows log says there is Error: 0xC0000409  in bluetoothapis.dll . Seems to be a STATUS_STACK_BUFFER_OVERRUN, but i have no idea what to do.

    uninstalling the Update solved the problem for now.

    Wednesday, May 25, 2016 6:55 AM
  • It happens for me as well. For some reason the .NET version works however, assigning an event to ValueChanged.
    Wednesday, May 25, 2016 8:58 AM
  • It happens for me as well. For some reason the .NET version works however, assigning an event to ValueChanged.
    Did you try this with 32 bit or 64 bit configuration? Try to change it to 32 and see if it still works.
    Wednesday, May 25, 2016 9:40 AM
  • For C: If I compile for 32-bit, it crashes. If I compile for 64-bit, it works.

    For .NET, it works regardless if I choose Any CPU, x86 or x64.

    Wednesday, May 25, 2016 5:50 PM
  • What happens is that the first notifications arrive as it should (my callback is called), but after my callback function has returned, the program crashes with an unhandled exception. After single step debugging when returning from my callback, I can see that it first calls DeviceIoControl which returns with ERROR_IO_PENDING (which is normal) but later the WaitForMultipleObjectsEx call fails (it returns -1) and if I then manually execute GetLastError() it returns ERROR_INVALID_HANDLE.
    Wednesday, May 25, 2016 5:52 PM
  • This issue only happens when running code using the Win32 Bluetooth APIs compiled for x86 architecture. There are no issues when using the same API compiled for AMD64 architecture. The WinRT APIs are not impacted across any architecture and we strongly recommend developers to use the Bluetooth WinRT APIs instead of the Win32 ones: https://msdn.microsoft.com/en-us/windows.devices.bluetooth.genericattributeprofile

    It has to do with the callback using a mismatched calling convention in Visual Studio by default, which x86 architecture are very sensitive about. This issue existed previously but only visibly manifested recently due to the KB3156421. To workaround this issue on x86 architecture and avoid leaking memory, please add CALLBACK before the declaration/definition of your callback routine. Then, make sure to c-cast (or reinterpret_cast) the callback function into PFNBLUETOOTH_GATT_EVENT_CALLBACK when giving it as parameter to BluetoothGATTRegisterEvent.

    Example:

    void CALLBACK HeartRateMeasurementEvent(
        _In_ BTH_LE_GATT_EVENT_TYPE EventType,
        _In_ PVOID EventOutParameter,
        _In_opt_ PVOID Context);
    
    ...
    
    hr = BluetoothGATTRegisterEvent(
            handle,
            CharacteristicValueChangedEvent,
            (PVOID)&registration,
            (PFNBLUETOOTH_GATT_EVENT_CALLBACK)HeartRateMeasurementEvent,
            NULL,
            &eventHandle,
            BLUETOOTH_GATT_FLAG_NONE);


    Friday, May 27, 2016 6:20 PM
  • This issue only happens when running code using the Win32 Bluetooth APIs compiled for x86 architecture. There are no issues when using the same API compiled for AMD64 architecture. The WinRT APIs are not impacted across any architecture and we strongly recommend developers to use the Bluetooth WinRT APIs instead of the Win32 ones: https://msdn.microsoft.com/en-us/windows.devices.bluetooth.genericattributeprofile

    It has to do with the callback using a mismatched calling convention in Visual Studio by default, which x86 architecture are very sensitive about. This issue existed previously but only visibly manifested recently due to the KB3156421. To workaround this issue on x86 architecture and avoid leaking memory, please add CALLBACK before the declaration/definition of your callback routine. Then, make sure to c-cast (or reinterpret_cast) the callback function into PFNBLUETOOTH_GATT_EVENT_CALLBACK when giving it as parameter to BluetoothGATTRegisterEvent.

    Example:

    void CALLBACK HeartRateMeasurementEvent(
        _In_ BTH_LE_GATT_EVENT_TYPE EventType,
        _In_ PVOID EventOutParameter,
        _In_opt_ PVOID Context);
    
    ...
    
    hr = BluetoothGATTRegisterEvent(
            handle,
            CharacteristicValueChangedEvent,
            (PVOID)&registration,
            (PFNBLUETOOTH_GATT_EVENT_CALLBACK)HeartRateMeasurementEvent,
            NULL,
            &eventHandle,
            BLUETOOTH_GATT_FLAG_NONE);


    I can confirm this fixes the issue!
    Friday, May 27, 2016 10:09 PM
  • This issue only happens when running code using the Win32 Bluetooth APIs compiled for x86 architecture. There are no issues when using the same API compiled for AMD64 architecture. The WinRT APIs are not impacted across any architecture and we strongly recommend developers to use the Bluetooth WinRT APIs instead of the Win32 ones:

    It has to do with the callback using a mismatched calling convention in Visual Studio by default, which x86 architecture are very sensitive about. This issue existed previously but only visibly manifested recently due to the KB3156421. To workaround this issue on x86 architecture and avoid leaking memory, please add CALLBACK before the declaration/definition of your callback routine. Then, make sure to c-cast (or reinterpret_cast) the callback function into PFNBLUETOOTH_GATT_EVENT_CALLBACK when giving it as parameter to BluetoothGATTRegisterEvent.

    Example:

    void CALLBACK HeartRateMeasurementEvent(
        _In_ BTH_LE_GATT_EVENT_TYPE EventType,
        _In_ PVOID EventOutParameter,
        _In_opt_ PVOID Context);
    
    ...
    
    hr = BluetoothGATTRegisterEvent(
            handle,
            CharacteristicValueChangedEvent,
            (PVOID)&registration,
            (PFNBLUETOOTH_GATT_EVENT_CALLBACK)HeartRateMeasurementEvent,
            NULL,
            &eventHandle,
            BLUETOOTH_GATT_FLAG_NONE);


    I can also confirm this fixed the problem. You said that you recommend to use the WinRT API instead, but as far as I could find in the documentation, it looks like it's .NET only. Is it available for native languages as well? (C/C++)
    Sunday, May 29, 2016 6:16 AM
  • This issue only happens when running code using the Win32 Bluetooth APIs compiled for x86 architecture. There are no issues when using the same API compiled for AMD64 architecture. The WinRT APIs are not impacted across any architecture and we strongly recommend developers to use the Bluetooth WinRT APIs instead of the Win32 ones:

    It has to do with the callback using a mismatched calling convention in Visual Studio by default, which x86 architecture are very sensitive about. This issue existed previously but only visibly manifested recently due to the KB3156421. To workaround this issue on x86 architecture and avoid leaking memory, please add CALLBACK before the declaration/definition of your callback routine. Then, make sure to c-cast (or reinterpret_cast) the callback function into PFNBLUETOOTH_GATT_EVENT_CALLBACK when giving it as parameter to BluetoothGATTRegisterEvent.

    Example:

    void CALLBACK HeartRateMeasurementEvent(
        _In_ BTH_LE_GATT_EVENT_TYPE EventType,
        _In_ PVOID EventOutParameter,
        _In_opt_ PVOID Context);
    
    ...
    
    hr = BluetoothGATTRegisterEvent(
            handle,
            CharacteristicValueChangedEvent,
            (PVOID)&registration,
            (PFNBLUETOOTH_GATT_EVENT_CALLBACK)HeartRateMeasurementEvent,
            NULL,
            &eventHandle,
            BLUETOOTH_GATT_FLAG_NONE);


    This fixed the problem with KB3156421 AND fixed a memory leakage problem that crashes my application after about 82.000 received Notification Callbacks.  As described here: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/1ea4159a-9639-4cd8-9732-e0f532aa3a2a/strange-behaviour-with-bluetooth-low-energy-on-windows-10?forum=windowsgeneraldevelopmentissues
    Monday, May 30, 2016 7:20 AM
  • You said that you recommend to use the WinRT API instead, but as far as I could find in the documentation, it looks like it's .NET only. Is it available for native languages as well? (C/C++)

    The API for GATT is supported in native language such as C++ (but not C) via WRL:

    https://msdn.microsoft.com/en-us/library/hh438466.aspx


    Tuesday, May 31, 2016 6:21 PM
  • And what advantages does this API has over the Win32 one? It looks like it has the same functionality and it just wraps all of the Win32 under another API.
    Sunday, June 5, 2016 9:32 AM
  • And what advantages does this API has over the Win32 one? It looks like it has the same functionality and it just wraps all of the Win32 under another API.

    I feel kind of the same. With BluetoothGATTRegisterEvent I can register a callback for multiple characteristics at the same time, meaning the events will be delivered in a synchronized order on the same thread.

    Last time I tried, the gatt read method in the WinRT API seems to issue two read requests to the BLE device rather than one which also seems quite stupid.

    I also haven't seem a good way to disconnect with the WinRT APIs. I can do that easily with the Win32 APIs by simply closing the handle to the device. Maybe disposing all the objects might work...

    With Win32 it also seems easier (even though very tedious to program and requires some researching efforts) to handle all the many different corner cases regarding getting notifications and re-establish things due to system pairing, pairing but service discovery failed, unpairing, unplugging bluetooth controller, plugging bluetooth controller into a different USB port, plugging in a different bluetooth controller etc. I had huge problems with the WinRT GATT APIs that they seem to throw random undocumented exceptions all the time when you do something that slightly deviate from normal conditions (that seem to come from internal calls to the Win32 APIs).

    One other thing I don't like (for both APIs) are the default scan parameters that can't be changed that are used when notifications are registered. For coin-cell-powered centrals it may be good to scan for 22.5 ms each 1280 ms but for stationary computers that runs on wall-power it's much better to have more "active" parameters since that means the peripheral will connect faster which in turn means both that the peripheral don't need to waste battery on advertising for a longer time, and that the user experience will be improved.

    For both APIs, I'd like an option when reading / writing characteristics / descriptors that it should not try if it is not connected. For many peripherals that has some kind of connection state it is pointless to have a blocking wait while reconnecting, and write the data after it has reconnected. The peripheral can't handle the write since the state is invalid. For example firmware upgrade over BLE, you often send some start command, followed by the firmware data. You can't really reconnect if the link timed out and continue in the middle. I'd rather want a fail return code immediately from the APIs and start over once it has reconnected, just how it's done on Android and iOS.

    What I like however is the ability to require encryption for the GATT operations. Both Android and iOS lack that, which is very strange from a security perspective that the app can't know whether the link is encrypted or not!

    Wednesday, June 8, 2016 12:17 AM
  • @EmilenL: Thank you for your detailed answer. I thought the Win32 API is poor, but seems like the WinRT API isn't better.

    Apart from this, is there anywhere a way to connect to a Peripheral device that is advertising WITHOUT pairing it in windows settings first? That is the stupidest thing ever...

    Thank you

    Wednesday, June 8, 2016 6:24 AM
  • @EmilenL: Thank you for your feedback. One of the main advantage of the WinRT APIs over the Win32 is that it is still improving vs. the Win32 APIs. We are currently actively addressing some of the concerns that you mentioned whereas the Win32 APIs will mostly remain as-is.

    Regarding the multiple reads sent, that is definitely not the expected behavior. Do you have more details on the repro condition (which operation and Cached/Uncached mode)? To disconnect from a device, you have to call "Dispose" (C#) on all BluetoothLEDevice and GattDeviceService objects (or Close via IClosable for C++). That is the equivalent of closing all file handles in Win32. Regarding the undocumented exceptions we are working right now to improve that experience to be more robust. Regarding the scan interval we understand the use case and the rationale behind it. At the current moment we don't have plans to expose the scan parameters to be controlled directly. For the read/write when the device is connected, you can check the connection state of the device from BluetoothLEDevice before attempting to write to it. You can subscribe for connection status changed event from BluetoothLEDevice.

    @kingkarl237: You can pair with a LE peripheral via API instead of from the settings page from WinRT. (https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.enumeration.deviceinformationpairing.aspx) See sample in: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing

    At this moment, the API does not support connecting to LE peripherals without pairing. With a very popular demand from developers, we are actively working on enabling that functionality for a future release.

    Thursday, June 9, 2016 6:38 PM
  • Hi,

    would it be possible for you to share your code? I'm having trouble finding recent examples of BLE GATT Profile drivers. The only samples I can find are outdated (the WDK 8.0 samples).

    Sunday, August 13, 2017 10:49 AM
  • This issue only happens when running code using the Win32 Bluetooth APIs compiled for x86 architecture. There are no issues when using the same API compiled for AMD64 architecture. The WinRT APIs are not impacted across any architecture and we strongly recommend developers to use the Bluetooth WinRT APIs instead of the Win32 ones:

    It has to do with the callback using a mismatched calling convention in Visual Studio by default, which x86 architecture are very sensitive about. This issue existed previously but only visibly manifested recently due to the KB3156421. To workaround this issue on x86 architecture and avoid leaking memory, please add CALLBACK before the declaration/definition of your callback routine. Then, make sure to c-cast (or reinterpret_cast) the callback function into PFNBLUETOOTH_GATT_EVENT_CALLBACK when giving it as parameter to BluetoothGATTRegisterEvent.

    Example:

    void CALLBACK HeartRateMeasurementEvent(
        _In_ BTH_LE_GATT_EVENT_TYPE EventType,
        _In_ PVOID EventOutParameter,
        _In_opt_ PVOID Context);
    
    ...
    
    hr = BluetoothGATTRegisterEvent(
            handle,
            CharacteristicValueChangedEvent,
            (PVOID)&registration,
            (PFNBLUETOOTH_GATT_EVENT_CALLBACK)HeartRateMeasurementEvent,
            NULL,
            &eventHandle,
            BLUETOOTH_GATT_FLAG_NONE);


    This fixed the problem with KB3156421 AND fixed a memory leakage problem that crashes my application after about 82.000 received Notification Callbacks.  As described here: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/1ea4159a-9639-4cd8-9732-e0f532aa3a2a/strange-behaviour-with-bluetooth-low-energy-on-windows-10?forum=windowsgeneraldevelopmentissues

    Thank you @kingkarl237! Following your activity feed finally brought me to that workaround. Still wasted lots of time...
    Wednesday, August 23, 2017 12:09 PM