Bug 29296 - Xamarin.iOS SIGSEGV crash when trying to discover services of a connected BLE peripheral
Summary: Xamarin.iOS SIGSEGV crash when trying to discover services of a connected BLE...
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 8.8.0
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2015-04-22 03:43 UTC by Markus Millfjord
Modified: 2017-07-25 12:49 UTC (History)
6 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Markus Millfjord 2015-04-22 03:43:46 UTC
I'm making a BLE cross-platform app in Xamarin, but fail to discover services of a connected peripheral.

Here's the stripped down code from the shared-project, just to be able to reproduce this issue;

internal class BleTransport
    //Private stuff
    private CBCentralManager Central = null;
    private CBPeripheral CurrentPeripheral = null;
    private bool IsScanning = false;

    internal BleTransport ()
        //Constructor -- initialize everything that needs to be initialized!
        Central = new CBCentralManager (DispatchQueue.MainQueue);

        //Setup delegates to the central's events
        Central.UpdatedState += (object sender, EventArgs e) => CentralStateChanged.Set ();
        Central.DiscoveredPeripheral += (object sender, CBDiscoveredPeripheralEventArgs e) => DiscoveredPeripheral (e.Peripheral, e.RSSI, e.AdvertisementData);             
        Central.ConnectedPeripheral += (object sender, CBPeripheralEventArgs e) => ConnectedPeripheral (e.Peripheral);
        Central.FailedToConnectPeripheral += (object sender, CBPeripheralErrorEventArgs e) => FailedToConnectPeripheral (e.Error, e.Peripheral);
        Central.DisconnectedPeripheral += (object sender, CBPeripheralErrorEventArgs e) => DisconnectedPeripheral (e.Error, e.Peripheral);

    readonly AutoResetEvent CentralStateChanged = new AutoResetEvent (false);
    private async Task<bool> WaitForCentralState (CBCentralManagerState state, TimeSpan timespan)
        Console.WriteLine("Waiting for state : " + state);

        //TODO; Keep track of time and decrease time-span accordingly
        bool timedout = false;

        while (!timedout && Central.State != state) 
            timedout = await Task.Run (delegate {
                //WaitOne returns false if we timeout
                return !CentralStateChanged.WaitOne (timespan);

        //Return true if we made it, amd false if we timedout
        return !timedout;

    private void StartScanning()
        Console.WriteLine("Start scan requestd!");

        if (!IsScanning) 
            IsScanning = true;

            Console.WriteLine("Kicking scan for peripherals!");
            CBUUID[] uuids = null;
            Central.ScanForPeripherals (uuids);

    private void StopScanning()
        Console.WriteLine("Stop scan requested!");

        if (IsScanning) 
            IsScanning = false;

    public async Task<bool> SetupTransport ()
        Console.WriteLine("Setting up transport!");

        //Wait for state update...
        if (!await WaitForCentralState (CBCentralManagerState.PoweredOn, TimeSpan.FromSeconds (2))) {

            //Failed detecting a powered-on BLE interface
            Console.WriteLine("Failed detecting usable BLE interface!");
            return false;

        //Kick scanning... 

        //Wait for discovery and connection to a valid peripheral, or timeout trying...
        await Task.Delay(10000);

        return true;

    #region Internal BLE utility methods

    private void DiscoveredPeripheral (CBPeripheral peripheral, NSNumber rssi, NSDictionary advertisementData)
        Console.WriteLine("DiscoveredPeripheral: " +peripheral.Name);

        //If the discovered device's name IS a valid serial number, AND match the serial number that we're intended to establish connection to...
        if (peripheral.Name == "MyPeripheralName") {

            Console.WriteLine("It's the peripheral we're looking for!");

            //Stop scanning...

            //Save reference and connect to it!
            CurrentPeripheral = peripheral;
            Central.ConnectPeripheral(CurrentPeripheral, new PeripheralConnectionOptions());

    private void ConnectedPeripheral (CBPeripheral peripheral)
        Console.WriteLine("ConnectedPeripheral: " + peripheral.Name);

        //Great -- explore services and charateristics and don't stop until we know that this device is legit!
        CurrentPeripheral.DiscoveredService +=  (object sender, NSErrorEventArgs e) => DiscoveredServices (e.Error);        
        CurrentPeripheral.DiscoveredCharacteristic += (object sender, CBServiceEventArgs e) => DiscoveredCharacteristics (e.Error, e.Service);

        //Kick service discovery!

    private void FailedToConnectPeripheral (NSError error, CBPeripheral peripheral)
        Console.WriteLine("FailedToConnectPeripheral: " + peripheral.Name);

    private void DisconnectedPeripheral (NSError error, CBPeripheral peripheral)
        Console.WriteLine("DisconnectedPeripheral: " + peripheral.Name + "(Error = " + error + ")");

    private void DiscoveredServices (NSError error)
        Console.WriteLine("DiscoveredService: " + error + "  -- " + NSThread.Current.IsMainThread);
        if (error != null) {

            //No error -- great!
            foreach (CBService service in CurrentPeripheral.Services) {
                Console.WriteLine ("Discovered service: " + service);
            //Opps -- failed!

            //Disconnect and indicate connection attempt finished

    private void DiscoveredCharacteristics (NSError error, CBService service)
        Console.WriteLine("DiscoveredCharacteristics for service: " + service);
        if (error != null) {

            //No error -- great!
            foreach (CBCharacteristic characteristic in service.Characteristics) {
                Console.WriteLine ("Discovered charateristic: " + characteristic);
            //Opps -- failed!

            //Disconnect and indicate connection attempt finished


The problem is that AFTER discovery is done, scanning is stopped, and the app connect to the peripheral and we arrive in the ConnectedPeripheral (CBPeripheral peripheral) function, I get a SIGSEGV crash with the following stack trace;

2015-04-21 23:33:37.205 BLE-test[1487:322866] critical: Stacktrace:

2015-04-21 23:33:37.206 BLE-test[1487:322866] critical:   at <unknown> <0xffffffff>
2015-04-21 23:33:37.206 BLE-test[1487:322866] critical:   at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <0xffffffff>
2015-04-21 23:33:37.207 BLE-test[1487:322866] critical:   at UIKit.UIApplication.Main (string[],intptr,intptr) [0x00005] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62
2015-04-21 23:33:37.207 BLE-test[1487:322866] critical:   at UIKit.UIApplication.Main (string[],string,string) [0x0001c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:45
2015-04-21 23:33:37.208 BLE-test[1487:322866] critical:   at BLEtest.Application.Main (string[]) [0x00008] in /Users/markus/Xamarin/BLE-test/BLE-test/Main.cs:17
2015-04-21 23:33:37.208 BLE-test[1487:322866] critical:   at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>

Followed by a native stack-trace that I've symbolicated into;

Incident Identifier: DCFCEE70-3D12-4F69-8303-777B2959563D
CrashReporter Key:   25c23a5bf636eb183168b18867096174f0d59b79
Hardware Model:      iPhone6,2
Process:             BLE-test [1241]
Path:                /private/var/mobile/Containers/Bundle/Application/C091012A-B1CB-464B-BDA5-B193C9C26BFC/BLE-test.app/BLE-test
Identifier:          com.your-company.BLEtest
Version:             1.0 (1.0)
Code Type:           ARM-64 (Native)
Parent Process:      launchd [1]

Date/Time:           2015-04-21 22:22:57.387 +0200
Launch Time:         2015-04-21 22:22:56.120 +0200
OS Version:          iOS 8.3 (12F70)
Report Version:      105

Exception Subtype: KERN_INVALID_ADDRESS at 0x000000000004b2c0
Triggered by Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x0000000195233270 __pthread_kill + 8
1   libsystem_pthread.dylib         0x00000001952d116c pthread_kill + 108
2   libsystem_c.dylib               0x00000001951aab14 abort + 108
3   BLE-test                        0x00000001001f6878 mono_handle_native_sigsegv (mini-exceptions.c:2360)
4   BLE-test                        0x0000000100200554 mono_sigsegv_signal_handler (mini.c:6879)
5   libsystem_platform.dylib        0x00000001952c8958 _sigtramp + 64
6   libobjc.A.dylib                 0x0000000194aa5ea8 _class_getVariable + 160
7   libobjc.A.dylib                 0x0000000194aa5ea8 _class_getVariable + 160
8   libobjc.A.dylib                 0x0000000194a9a934 object_getInstanceVariable + 72
9   BLE-test                        0x00000001002b10b0 get_raw_gchandle (runtime.m:304)
10  BLE-test                        0x00000001002b1044 get_gchandle (runtime.m:311)
11  BLE-test                        0x00000001002b0c6c xamarin_get_gchandle (runtime.m:317)
12  BLE-test                        0x00000001002b0bc0 xamarin_get_nsobject_with_type_for_ptr_created (runtime.m:201)
13  BLE-test                        0x00000001002b9508 xamarin_trampoline (.monotouch-trampoline-setup-callstack.inc:181)
14  CoreBluetooth                   0x0000000182f37198 -[CBPeripheral handleServicesDiscovered:] + 740
15  CoreBluetooth                   0x0000000182f34b38 -[CBPeripheral handleMsg:args:] + 280
16  CoreBluetooth                   0x0000000182f309d0 -[CBCentralManager xpcConnection:didReceiveMsg:args:] + 160
17  libdispatch.dylib               0x00000001950ed990 _dispatch_call_block_and_release + 20
18  libdispatch.dylib               0x00000001950ed950 _dispatch_client_callout + 12
19  libdispatch.dylib               0x00000001950f80a0 _dispatch_queue_drain + 1444
20  libdispatch.dylib               0x00000001950f0a58 _dispatch_queue_invoke + 128
21  libdispatch.dylib               0x00000001950f1db8 _dispatch_main_queue_callback_4CF + 500
22  CoreFoundation                  0x000000018327f7f4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
23  CoreFoundation                  0x000000018327d89c __CFRunLoopRun + 1488
24  CoreFoundation                  0x00000001831a92d0 CFRunLoopRunSpecific + 392
25  GraphicsServices                0x000000018c9c76f8 GSEventRunModal + 164
26  UIKit                           0x0000000187d6efa8 UIApplicationMain + 1484
27  BLE-test                        0x00000001000a0b94 wrapper_managed_to_native_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 340
28  BLE-test                        0x000000010007e60c UIKit_UIApplication_Main_string___intptr_intptr + 44
29  BLE-test                        0x000000010007e5c8 UIKit_UIApplication_Main_string___string_string + 184
30  BLE-test                        0x0000000100050110 BLEtest_Application_Main_string__ + 160
31  BLE-test                        0x000000010017c06c wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 156
32  BLE-test                        0x0000000100202614 mono_jit_runtime_invoke (mini.c:6737)
33  BLE-test                        0x000000010024d31c mono_runtime_invoke (object.c:2842)
34  BLE-test                        0x00000001002513f8 mono_runtime_exec_main (object.c:4099)
35  BLE-test                        0x00000001002afa34 xamarin_main (monotouch-main.m:400)
36  BLE-test                        0x00000001001ca924 main + 92
37  libdyld.dylib                   0x000000019511aa04 start + 0

Observations and thoughts;

If I remove the delegates to the peripheral after it has been connected, but before I try to discover its services (which means that I'll never see the result of the discovery, but just for test), the DiscoverService routine does NOT result in a crash;

// CurrentPeripheral.DiscoveredService += (object sender, NSErrorEventArgs e) => ...    
// CurrentPeripheral.DiscoveredCharacteristic += (object sender, ... 

Likewise, I've also tried to keep the delegates above, but remove the actual call to DiscoverServices and that also work without crashing (which is again a stupid test perhaps, but I just wanted to rule-out that something happened when I assigned the delegates in the first place).

I've also read about other peoples experiences with these kind of issues/errors and someone said that it's a GC-issue where an object might be GC'd even though it's still referenced?

Someone also mentioned that things worked in Release-mode but not in debug mode -- so I've tested to run my app in release which ALSO seems to work -- but I don't have any UI so I can't guarantee that is actually works -- but I do know that it does not crash with SIGSEGV...

I'm confused. Please help me understand why Xamarin does not like me. I'm happy to adjust and play by the Xamarin-rules, as long as I understand the constraints and what I can/can't do.
Comment 1 Markus Millfjord 2015-04-22 03:52:57 UTC
Also worth mentioning;

1) The BleTransport class above is invoked by the main-thread in the ViewController's "ViewDidAppear"-method. Previously I was unsuccessful in discovering my peripherals too, and I found that that was due to me creating an instance of my BleTransport in an async-thread.

2) The trace says Exception Type:  EXC_BAD_ACCESS (SIGABRT) and KERN_INVALID_ADDRESS which makes me believe that it's actually something that is GC'd. The symbolicated logs from iOS show that the services ARE indeed discovered and that the crash occur when trying to report those findings back to my event handlers "CurrentPeripheral.DiscoveredService +=  (object sender,
NSErrorEventArgs e) => ...". The fact that removing that event handler prevent the crash from happening is also interesting, and strengthen this argument I'd say.

3) If an object somewhere is GC'd, how can I see which one to fix this? In release-mode, things seem to work (I don't know coz I can't see the Console printouts, but I do know that things does not crash). What's the difference in GC behavior between debug-mode and release-mode? I'm using Xamarin Studio BTW. 

Thank you for your help -- looking forward to your feedback and suggestions. 
Comment 2 Markus Millfjord 2015-04-22 06:14:25 UTC
More digging...;

I just tried to see if the error was the callback/event-handlers inside the CBPeripheral, or the actual DiscoverServices method call. So I tried to call the function and wait 500ms and then see if the services had been discovered in my peripheral object;

Console.WriteLine ("List of services (before discovery attempt)");
if (CurrentPeripheral.Services != null)
    foreach (CBService service in CurrentPeripheral.Services) {
        Console.WriteLine ("Service: " + service);

await Task.Delay(500);

Console.WriteLine ("List of services (after discovery attempt)");
if (CurrentPeripheral.Services != null)
    foreach (CBService service in CurrentPeripheral.Services) {
        Console.WriteLine ("Service: " + service);

... and it works! Hence, this means that the call to DiscoverServices works just fine, but the callbacks does not.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2015-04-23 07:34:17 UTC
This crash occurs when we try to marshal a call from Objective-C to C# (in other words when Objective-C tries to invoke one of your event handlers).

Unfortunately I don't have any BLE devices, so I can't try this for myself, which means I'll have to ask you questions until we narrow it down.

First: does the crash occur on device as well, or is it only in the simulator?
Comment 4 Markus Millfjord 2015-04-23 16:38:18 UTC
Ok, problem solved. A newbie thing, of course...

When I launched Xamarin Studio and started this project, I played around and looked at the different options, settings, features, menus etc, just to get a grip of the concept as such. One of the things I found was the iOS-build options where one could change the _Linker Options_. I figured that "Link all assemblies" was a good choice, just to be on the safe side, rather than "Don't link" which was preselected. 

Didn't think more about it and continued with the coding.

But when I found the issue raised and explain in this thread, you desperately start to search for anything anywhere, and I started to hunt for GC issues which was what thought was the source of the error. So, reading through the best-practices for Memory management at this link (http://developer.xamarin.com/guides/cross-platform/deployment,_testing,_and_metrics/memory_perf_best_practices/), I found that;
    The Link All Assemblies should be used with caution as it may break the application in unexpected ways.

Hence, I changed back to _Don't link_ and now everything works like a charm... 
Stuped newbie error? Yes, for sure, but I hope that someone else making the same misstake will find this post and find it useful.

Comment 5 Rolf Bjarne Kvinge [MSFT] 2015-04-24 03:24:30 UTC
Enabling the linker should not have this effect, so I'm reopening this.

@Paola, do you have a BLE device you can try this with and see if you can reproduce it?
Comment 6 Markus Millfjord 2015-04-24 16:23:36 UTC
Ok -- well, then I can provide more "strangeness" that occurred while testing, for you to try to reproduce;

The CBCentralManager only worked (e.g., received callbacks when discovering a peripheral) when I used Lambda "+="-syntax to hook-in my functions. It did NOT work (same type of crash behavior as the service-discovery stuff in this bug-post) when extending CBCentralManagerDelegate and overriding methods... Stack-traced showed the same thing; CoreBluetooth managed to discover a device, but crashed when handing over to my Xamarin code-base. If no peripheral was within range, no crash occurred.

But for some reason the Lambda-approach worked for the CBCentralManager.

As for reproducing the behavior; download any suitable BLE test-app for iOS with support for peripheral-mode and start to advertise from it -- it will/should turn up and allow you to recreate by bug.
Comment 7 Rolf Bjarne Kvinge [MSFT] 2015-04-27 12:05:35 UTC
I haven't been able to create a test case, this is the project I have: https://github.com/rolfbjarne/bleexplorer, and it does not crash at all.

Could you zip up and attach your project so that we can try to figure out if there's something else going on?
Comment 8 Paola Villarreal 2015-04-27 16:49:46 UTC
Tried to reproduce with Rolf's sample and an Estimote device and it won't crash on device. 

Version info:

Xamarin Studio
Version 5.9 (build 431)
Installation UUID: 226bee58-de6e-4832-9b4c-85cdb95c4472
	Mono 4.0.0 ((detached/d136b79)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 400000143

Apple Developer Tools
Xcode 6.3.1 (7703)
Build 6D1002

Version: (Business Edition)
Hash: 18b50a1
Branch: master
Build date: 2015-04-27 12:05:22-0500

Version: (Business Edition)
Android SDK: /Users/paw/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		2.3   (API level 10)
		4.0.3 (API level 15)
		4.4   (API level 19)
Java SDK: /usr
No Java runtime present, requesting install.

Xamarin Android Player
Not Installed

Version: (Business Edition)

Build Information
Release ID: 509000431
Git revision: 7560726734fc7267de2fa9abed2509968deefaa8
Build date: 2015-04-17 19:25:48-04
Xamarin addins: 2e772c734ab3148054eae7bf8949f340fdeb5e5e

Operating System
Mac OS X 10.10.3
Darwin paw.local 14.3.0 Darwin Kernel Version 14.3.0
    Mon Mar 23 11:59:05 PDT 2015
    root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64
Comment 9 Johannes Rudolph 2015-07-01 09:42:46 UTC
Hitting the same issue here. I think I could narrow it down further. Using latest Xamarin and iOS 8.4 Simulator (which doesn't support Bluetooth but I still get crashes anyway): 

I have code like this: 
            _manager = new CBCentralManager( null, DispatchQueue.MainQueue, options); // we will receive all callbacks on the main thread
            _manager.UpdatedState += HandleCentralManagerUpdatedState;
            _manager.DiscoveredPeripheral += HandleDeviceDiscovered;
            _manager.FailedToConnectPeripheral += HandleFailedToConnectPeripheral;
            _manager.ConnectedPeripheral += HandleConnectedPeripheral;
            _manager.DisconnectedPeripheral += HandleDisconnectedPeripheral;

I do nothing with the _manager (i.e. no scan etc.) because the UpdateState event is never fired (to be expected in simulator and perfectly fine). 

Once I'm done with whatever else I'm doing, I dispose the _manager: 


Once the main runloop has however had a chance to run I suddenly see a crash:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x08d7d69a __pthread_kill + 10
1   libsystem_pthread.dylib       	0x08dabf19 pthread_kill + 101
2   libsystem_sim_c.dylib         	0x08b35a5a abort + 156
3   libmonosgen-2.0.dylib         	0x06fbd851 mono_handle_native_sigsegv + 705
4   libmonosgen-2.0.dylib         	0x0700ef25 mono_arch_handle_altstack_exception + 165
5   libmonosgen-2.0.dylib         	0x06f115e0 mono_sigsegv_signal_handler + 432
6   libsystem_platform.dylib      	0x08d9d03b _sigtramp + 43
7   ???                           	0xffffffff 0 + 4294967295
8   libmonosgen-2.0.dylib         	0x06f11430 mono_sigill_signal_handler + 48
9   com.apple.CoreBluetooth       	0x00ab02b2 __62-[CBXpcConnection initWithDelegate:queue:options:sessionType:]_block_invoke35 + 49
10  libdispatch.dylib             	0x08a4ed8a _dispatch_call_block_and_release + 15
11  libdispatch.dylib             	0x08a6becf _dispatch_client_callout + 14
12  libdispatch.dylib             	0x08a54ee3 _dispatch_main_queue_callback_4CF + 677
13  com.apple.CoreFoundation      	0x073d18ee __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14

I agree its a native->managed dispatch problem. Weirdly enough, this goes away when I do: 
            _manager.Delegate = null;

Should be trivial to build a repro case for this, alloc an instance of CBCentralManager, hook up event handlers and dispose it, wait for the run loop to run and boom!

XS Info: 
Xamarin Studio
Version 5.9.4 (build 5)
Installation UUID: 3cbf1b60-0560-4942-8de5-aedf17c5251e
	Mono 4.0.2 ((detached/c99aa0c)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 400020005

Apple Developer Tools
Xcode 6.4 (7720)
Build 6E35b

Version: (Indie Edition)
Hash: ef8c2f7
Branch: master
Build date: 2015-06-22 21:28:32-0400

Version: (Indie Edition)
Android SDK: /Users/jr/Library/Developer/Xamarin/android-sdk-mac_x86
	Supported Android versions:
		2.3   (API level 10)
		4.0.3 (API level 15)
		4.2   (API level 17)
		4.3   (API level 18)
		4.4   (API level 19)
Java SDK: /usr
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

Xamarin Android Player
Not Installed

Not Installed

Build Information
Release ID: 509040005
Git revision: 8010a90f6e246b32364e3fb46ef2c9d1be9c9a2b
Build date: 2015-06-08 16:52:06-04
Xamarin addins: 7e93e9c3503f28770f23ce1b7eafd829919f18e8

Operating System
Mac OS X 10.10.4
Darwin iDevBook01.local 14.4.0 Darwin Kernel Version 14.4.0
    Thu May 28 11:35:04 PDT 2015
    root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64
Comment 10 John Miller [MSFT] 2017-07-25 12:49:05 UTC
Because we have not received a reply to our request for more information, we are marking this issue as RESOLVED→NORESPONSE. If you are still encountering this issue on the latest Xamarin.iOS, please don’t hesitate to reopen the ticket with the requested information. Thanks!