Rightpoint/RZBluetooth

RZBConnectCommand executeCommandWithContext:error: crashes with assert that peripheral != nil

Closed this issue · 7 comments

Sometimes when turning off Bluetooth while connected to a peripheral the app crashes in executeCommandWithContext:error: on RZBConnectCommand because

CBPeripheral *peripheral = [context corePeripheralForUUID:self.peripheralUUID];

This peripheral is nil. This does not happen every time but does happen sometimes.

Is this the assert that fires?

NSAssert(peripheral.state != CBPeripheralStateConnected, @"Should not execute connect on connected peripheral");

Thinking it through, I can imagine some reset scenarios validly triggering this. I'd love a log with all of the delegate interactions if you could thought to make sure it isn't catching a strange scenario. You can email it to me (brian.king@raizlabs.com) if you aren't comfortable posting it here.

A PR removing the commit would be good, but I want to verify that if a connect command is sent while connected that the delegate is still triggered.

No the assert that fires is a CoreBluetooth one "peripheral != nil" with a message. I cannot reproduce it consistently. I'll post logs if I am able to reproduce it again. So far in weeks of working I have seen this crash happen twice.

@KingOfBrian this continues to happen. Here's the crash log if it helps

Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 0x186bd3d38 __exceptionPreprocess
1  libobjc.A.dylib                0x1860e8528 objc_exception_throw
2  CoreFoundation                 0x186bd3c0c +[NSException raise:format:]
3  Foundation                     0x187562c24 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
4  CoreBluetooth                  0x18bff25cc -[CBCentralManager connectPeripheral:options:]
5  MyBundle                      0x10317ca0c -[RZBConnectCommand executeCommandWithContext:error:] (RZBCommand.m:167)
6  MyBundle                      0x10317f6c8 -[RZBCommandDispatch executeCommand:] (RZBCommandDispatch.m:132)
7  MyBundle                      0x10317eed8 __38-[RZBCommandDispatch dispatchCommand:]_block_invoke.35 (RZBCommandDispatch.m:60)
8  libdispatch.dylib              0x186559088 _dispatch_call_block_and_release
9  libdispatch.dylib              0x186559048 _dispatch_client_callout
10 libdispatch.dylib              0x186565b74 _dispatch_main_queue_callback_4CF$VARIANT$mp
11 CoreFoundation                 0x186b7bf20 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
12 CoreFoundation                 0x186b79afc __CFRunLoopRun
13 CoreFoundation                 0x186a9a2d8 CFRunLoopRunSpecific
14 GraphicsServices               0x18892bf84 GSEventRunModal
15 UIKit                          0x190047880 UIApplicationMain

Are you still seeing this issue? I'm curious if the UUID for the peripheral may of just be "unbonded" from the phone, but the UUID was persisted. I'm seeing a case of un-bonded devices where the peripheral UUID's are returning nil peripherals that I think may be the source of this issue.

@KingOfBrian I had to add a check to prevent this from happening

I added this below the CBPeripheral *peripheral = [context corePeripheralForUUID:self.peripheralUUID]; line

if (peripheral == nil) {
        return NO;
    }

How could the device be unbounded by itself?

The peripheral can loose bonding state if it's forgotten in Settings. I'm going to put a guard in to make the failure case more obvious and if RZBluetooth can't find a CBPeripheral, it will not create a RZBPeripheral. This should make the failure routes more obvious. Also adding some comments as to how this happens.

Fixed in #95