Closed lambourn closed 4 years ago
Hi @lambourn,
Here's the implementation of bufferFromData. Looking at it, I don't see any reasons for the underlying buffer to become invalidated. The implementation puts a strong reference to the instance, so it shouldn't be deallocated prematurely. On the other side, what looks suspicious is that the NSData
's buffer itself can get invalidated if a modification happens in the meantime. The documentation says that:
For a mutable data object, the returned pointer is valid until the data object is deallocated or the data is mutated.
I have no knowledge who else owns references to this NSData
object in your app and what's going on with it. Can you validate whether it's kept intact?
You can also try running your app with Xcode's AddressSanitizer enabled so that you catch any other memory issues which might indirectly cause this one.
Hi @mbektchiev,
thanks for the insights!
The NSData object is owned by the CBCharacteristic
we read data from. As per the documentation for CBCharacteristic.value
, the property is non-mutable but retained
.
Regarding the JS runtime error, the following could explain it: new data has been received by CoreBlutooth and the existing NSData
object in the value property was released by the Obj-C memory management and replaced by a new NSData
object (this is how I understand retained
). That could explain, why the previously stored strong reference to NSData
has been invalidated, leading to a detached backing ArrayBuffer
in the JS realm.
As mentioned, we only see this error happening very, very rarely - which maybe again hints to memory / ARC management - but if it happens, the app crashes.
One workaround for now is to check if the data view is still ok to use by checking byteLength
:
const view = new Uint8Array(buffer);
if (view.byteLength === 0) {
// view's ArrayBuffer is detached!
...
} else {
// safe to access the data
...
}
at least this does not crash the app. Another thing I will try is to create a copy of the new NSData
that is read from CBCharacteristic.value
and pass that on instead of the retained reference.
using above approach of copying the data held by the source NSData
and having the additional gurad check on the data view's byteLength
fixes the issue for me.
Issue can be closed.
Environment Provide version numbers for the following components (information can be retrieved by running
tns info
in your project folder or by inspecting thepackage.json
of the project):Describe the bug
In our app we use CoreBluetooth to read binary data from BLE/GATT peripherals. The received data (
NSData
) is passed asArrayBuffer
to the NativeScript application tier usinginterop.bufferFromData(nsData)
. Typically, this just works fine.In some situations, typically during ongoing and continous data transfers, we see crashes due to the
ArrayBuffer
being detached from the data view (Uint8Array
) that is used to access the data. Error message "TypeError: Underlying ArrayBuffer has been detached from the view"What strikes me here is that from the application perspective, the access of the data view happens synchronously after the ArrayBuffer was passed to the place where processing happens.
Pseudo code / sending side:
Pseudo code / processing side:
So somehow the
NSData
seems to be gone or theArrayBuffer
has been detached.Any ideas what would cause the ios-runtime to invalidate/free/re-allocate the
NSData
?Native Stack Trace