For a personal project, I have been writing some library to interface the CoreBluetooth API with the go language. Because of what it does, that library is written in objective-C with ARC disabled.
One function I had to write takes a memory buffer (allocated with malloc() on the go side), creates an NSData object out of it to pass the data to the writeValue:forCharacteristic:type: CoreBluetooth method, and then releases the NSData as well as the original memory buffer:
void Write(CBPeripheral *p, CBCharacteristic *c, void *bytes, int len) {
NSData *data = [NSData dataWithBytesNoCopy:bytes length:len freeWhenDone:true];
[p writeValue:data forCharacteristic:c type:CBCharacteristicWriteWithoutResponse];
[data release];
}
One thing I noticed is that the retainCount for data increases during the writeValue:forCharacteristic:type: API call. It is 1 before, and 2 after. This is surprising to me, because the documentation says "This method copies the data passed into the data parameter, and you can dispose of it after the method returns."
I suspects this results in a memory leak. Am I missing something here ?
Core OS
RSS for tagExplore the core architecture of the operating system, including the kernel, memory management, and process scheduling.
Post
Replies
Boosts
Views
Activity
Hi all:
I am experimenting with Finder extensions. I’d like to be able to add a context menu to all folder locations. I believe the code below should work, but it doesn’t. If I hard code a path, it does work. Any tips on what I am missing?
Thanks!
// Doesn’t work
FIFinderSyncController.default().directoryURLs = nil
// Works for user folder
var myFolderURL = URL(fileURLWithPath: "/users/exampleuser")
FIFinderSyncController.default().directoryURLs = [self.myFolderURL]
Hi, I am trying to write simple code that my iPhone acts as BLE peripheral (advertise packet). but i cannot see the advertisement on other devices that do scanning. What could be the cause?
Code snippet
=============
import SwiftUI
import CoreBluetooth
// 1. Conform to CBPeripheralManagerDelegate
class BLEAdvertiser: NSObject, ObservableObject, CBPeripheralManagerDelegate {
var peripheralManager: CBPeripheralManager?
// 2. Start advertising
func startAdvertising() {
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
}
// 3. CBPeripheralManagerDelegate method called when state changes
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
switch peripheral.state {
case .poweredOn:
// Define a service UUID
let serviceUUID = CBUUID(string: "1234") // Custom UUID for your service
// Create a CBMutableService
let service = CBMutableService(type: serviceUUID, primary: true)
// Add service to the peripheral manager
peripheralManager?.add(service)
// Start advertising the service
let advertisementData: [String: Any] = [
CBAdvertisementDataServiceUUIDsKey: [serviceUUID],
CBAdvertisementDataLocalNameKey: "My iPhone"
]
peripheralManager?.startAdvertising(advertisementData)
print("Started advertising!")
case .poweredOff:
print("Bluetooth is powered off.")
case .resetting:
print("Bluetooth is resetting.")
case .unauthorized:
print("Bluetooth access is unauthorized.")
case .unsupported:
print("Bluetooth is unsupported on this device.")
case .unknown:
print("Bluetooth state is unknown.")
@unknown default:
print("A new state that we don’t know about.")
}
}
// 4. Optional: Handle peripheral manager adding service
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
if let error = error {
print("Failed to add service: \(error.localizedDescription)")
return
}
print("Service added successfully!")
}
}
struct ContentView: View {
@StateObject private var bleAdvertiser = BLEAdvertiser()
var body: some View {
VStack {
Text("BLE Advertising")
.font(.largeTitle)
.padding()
Button(action: {
bleAdvertiser.startAdvertising()
}) {
Text("Start Advertising")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
}
Hello,
using UIDocumentPickerViewController and startAccessingSecurityScopedResource(), I can access to a directory on iOS using Bookmark data, but when I save a Bookmark data, security-scoped bookmark not survive quitting the app and re-launching it.
I used the Apple example here but my app doesn't appear in Settings > Privacy > Files and Folders ?
Security-scoped bookmark is-it available on iOS ?
Thanks.
I would like to know the maximum number of Bluetooth peripherals that can be connected to a mobile phone. Is there a specific limit on the number of Bluetooth peripherals, or what is the connection number related to
Hello,
I’m working on creating an NFC-enabled Apple Wallet pass and I need assistance with the proper implementation of the pass.json file to include NFC functionality. My goal is to enable NFC interactions, such as tapping to unlock a door or interacting with other NFC systems.
Here is what I have done so far:
Set up a Pass Type ID and Certificates:
I have registered a Pass Type ID in my Apple Developer account.
I have generated and installed the required certificates (Pass Type ID certificate and WWDR certificate).
Backend Integration:
I have set up a backend service for generating passes, and I can successfully create and deliver standard Wallet passes without the NFC functionality.
Adding the NFC Field:
I understand that to enable NFC interactions, I need to add an nfc dictionary to the pass.json file.
The key components for NFC include the encryptionPublicKey, message, and payload.
Here’s an example of my current pass.json:
{
"formatVersion": 1,
"passTypeIdentifier": "pass.com.example.mypass",
"serialNumber": "123456",
"teamIdentifier": "TEAMID12345",
"webServiceURL": "https://example.com/api/passes",
"authenticationToken": "my_secure_token",
"nfc": {
"message": "Tap to unlock door",
"encryptionPublicKey": "MY_ENCRYPTION_PUBLIC_KEY",
"payload": "encrypted_nfc_payload"
},
"organizationName": "My Company",
"description": "NFC-Enabled Access Pass",
"logoText": "My NFC Pass",
"foregroundColor": "rgb(255, 255, 255)",
"backgroundColor": "rgb(0, 0, 0)",
"barcode": {
"format": "PKBarcodeFormatQR",
"message": "https://example.com",
"messageEncoding": "iso-8859-1"
}
}
Questions:
Are there any additional steps or configurations required to ensure that NFC is enabled in the pass?
Is there a specific method to test or validate NFC functionality in the pass to debug why it’s not being activated?
Any guidance or solutions to enable NFC in this pass would be greatly appreciated.
Thank You
I’m working on an iOS app that uses Bluetooth Low Energy (BLE) to communicate with a peripheral device. Currently, we scan by service ID and successfully connect in the background.
Would it be acceptable (and within Apple's guidelines) to poll data from the device every 5 seconds while in the background?
Or is it required to have the BLE device notify?
We have a sandboxed swift app with an associated network extension where both write to the same log file in a shared container (via NSFileCoordinator)
On sonoma all was good. With sequoia, we get a popup requesting access to the file from the user.
I realize this is all in the name of security, but is there any way to prevent this popup?
alf
HI,
I am having some discrepancies with FileManager. Currently, FileManager.default.isReadableFile(atPath: path) returns false, where fileExists(atPath: path) is true - I was able to write a new file at the same location. Does anyone have any ideas as to why I would be able to write but not read a file?
Thanks for any advice!
I have an application built with .NET MAUI that uses the CoreBluetooth API to scan for our devices. As we need extanded advertisings we want to check if the device supports it. Our problem is that the query by using the "supports" method of CBCentralManger with argument "extendedScanAndConnect" gives us not always the same result.
When called at the app start we get false (=> not supported)
When called when the state of CBCentralManager changes to "poweredOn" we get false (=> not supported)
When called later when a button to scan is pressed we get true (=> supported)
How can we get the information if extended scan is supported at startup of our app?
Hardware: iPhone 14
OS: iOS 18.0.1
Since I haven't heard so much as a peep from Apple on this, I thought I'd take a poll here on how long I could expect an easily reproducible (albeit possibly obscure) kernel panic to be fixed.
I was under the impression that kernel panics were a big deal but it's been almost 2 months since I updated from macOS 14 to macOS 15.0 dev beta 7 / public beta 5 when I originally came across and reported a panic triggered while playing StarCraft II.
I've been able to consistently trigger panics playing certain (maybe all) Co-op maps in SC2 and since my first report Aug 22, I've filed 8 additional bug reports, each automatically generated after hitting yet another panic. (I'm not sure exactly who is able to view these but for what it's worth, these are the reports I've filed so far: FB14886510, FB14905773, FB14960435, FB15304609, FB15391195, FB15467943, FB15468127, FB15491485, FB15491684.)
A few other people have reported the issue to SC2's developer, Blizzard, and apparently Blizzard has acknowledged they're aware of the problem so it's safe to rule out the possibility of a hardware defect or other issue specific only to my computer.
The logs point the blame at the AppleDCP driver, although I suppose the problem could technically be in the DCP firmware instead. Regardless, Apple's code is clearly at fault here.
I'll admit the importance of a video game isn't exactly like keeping the power on at a hospital but I don't know why it would be deemed particularly unimportant either.
At 53 days in, am I wrong to expect this to have been fixed by now or is Apple really being that slow?
I'm trying to use the example code https://developer.apple.com/documentation/foundation/filemanager/2765464-enumerator to exclude a sub directory, but the .skipDescendants doesn't seem to do what I expect.
Should this work? I want to ignore everything in the __CYCLES folder inside topLevelFolder. But those paths are listed along with all the other files/folders. I never see "Skipping Cycles" in my output.
import Foundation
let rootPath = "/Volumes/volumename/topLevelFolder"
let topLevelFolderURL = URL(fileURLWithPath: rootPath)
let localFileManager = FileManager()
let resourceKeys = Set<URLResourceKey>([.nameKey, .isDirectoryKey, .fileSizeKey])
let directoryEnumerator = localFileManager.enumerator(at: topLevelFolderURL, includingPropertiesForKeys: Array(resourceKeys), options: [.skipsHiddenFiles, .skipsPackageDescendants])!
for case let fileURL as URL in directoryEnumerator {
guard let resourceValues = try? fileURL.resourceValues(forKeys: resourceKeys),
let isDirectory = resourceValues.isDirectory,
let name = resourceValues.name,
let size = resourceValues.fileSize
else {
continue
}
if isDirectory {
if name == "__CYCLES" {
directoryEnumerator.skipDescendants()
print("Skipping Cycles")
}
} else {
print("\(fileURL.path) = \(size)")
}
}
I’ve talked about EINTR a bunch of times here on DevForums. Today I found myself talking about it again. On reading my other explanations, I didn’t think any of them were good enough to link to, so I decided to write it up properly.
If you have questions or comments, please put them in a new thread here on DevForums. Use the App & System Services > Core OS topic area so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Understanding EINTR
Many BSD-layer routines can fail with EINTR. To see this in action, consider the following program:
import Darwin
func main() {
print("will read, pid: \(getpid())")
var buf = [UInt8](repeating: 0, count: 1024)
let bytesRead = read(STDIN_FILENO, &buf, buf.count)
if bytesRead < 0 {
let err = errno
print("did not read, err: \(err)")
} else {
print("did read, count: \(bytesRead)")
}
}
main()
It reads some bytes from stdin and prints the result. Build this and run it in one Terminal window:
% ./EINTRTest
will read, pid: 13494
Then, in other window, stop and start the process by sending it the SIGSTOP and SIGCONT signals:
% kill -STOP 13494
% kill -CONT 13494
In the original window you’ll see something like this:
% ./EINTRTest
will read, pid: 13494
zsh: suspended (signal) ./EINTRTest
%
did not read, err: 4
[1] + done ./EINTRTest
When you send the SIGSTOP the process stops and the shell tells you that. But looks what happens when you continue the process. The read(…) call fails with error 4, that is, EINTR. The read man page explains this as:
[EINTR] A read from a slow device was interrupted before any data arrived by the delivery of a signal.
That’s true but unhelpful. You really want to know why this error happens and what you can do about it. There are other man pages that cover this topic in more detail — and you’ll find lots of info about it on the wider Internet — but the goal of this post is to bring that all together into one place.
Signal and Interrupts
In the beginning, Unix didn’t have threads. It implemented asynchronous event handling using signals. For more about signals, see the signal man page.
The mechanism used to actually deliver a signal is highly dependent on the specific Unix implementation, but the general idea is that:
The system decides on a specific process (or, nowadays, a thread) to run the signal handler.
If that’s blocked inside the kernel waiting for a system call to complete [1], the system unblocks the system call by failing it with an EINTR error.
Thus, every system call that can block [2] might fail with an EINTR. You see this listed as a potential error in the man pages for read, write, usleep, waitpid, and many others.
[1] There’s some subtlety around the definition of system call. On traditional Unix systems, executables would make system calls directly. On Apple platforms that’s not supported. Rather, an executable calls a routine in the System framework which then makes the system call. In this context the term system call is a shortcut for a System framework routine that maps to a traditional Unix system call.
[2] There’s also some subtlety around the definition of block. Pretty much every system call can block for some reason or another. In this context, however, a block means to enter an interruptible wait state, typically while waiting for I/O. This is what the above man page quote is getting at when it says slow device.
Solutions
This is an obvious pitfall and it would be nice if we could just get rid of it. However, that’s not possible due to compatibility concerns. And while there are a variety of mechanism to automatically retry a system call after a signal interrupt, none of them are universally applicable. If you’re working on a large scale program, like an app for Apple’s platforms, you only good option is to add code to retry any system call that can fail with EINTR.
For example, to fix the program at the top of this post you might wrap the read(…) system call like so:
func readQ(_ d: Int32, _ buf: UnsafeMutableRawPointer!, _ nbyte: Int) -> Int {
repeat {
let bytesRead = read(d, buf, nbyte)
if bytesRead < 0 && errno == EINTR { continue }
return bytesRead
} while true
}
Note In this specific case you’d be better off using the read(into:retryOnInterrupt:) method from System framework. It retries by default (if that’s not appropriate, pass false to the retryOnInterrupt parameter).
You can even implement the retry in a generic way. See the errnoQ(…) snippet in QSocket: System Additions.
Library Code
If you’re writing library code, it’s important that you handle EINTR so that your clients don’t have to. In some cases it might make sense to export a control for this, like the retryOnInterrupt parameter shown in the previous section, but it should default to retrying.
If you’re using library code, you can reasonably expect it to handle EINTR for you. If it doesn’t, raise that issue with the library author. And you get this error back from an Apple framework, like Foundation or Network framework, please file a bug against the framework.
Consider this very trivial code which accesses the operatingSystemVersion property of NSProcessInfo as documented at https://developer.apple.com/documentation/foundation/nsprocessinfo/1410906-operatingsystemversion
osversion.c:
#include <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
fprintf(stderr, "OS version: %ld.%ld.%ld\n", osVersion.majorVersion, osVersion.minorVersion, osVersion.patchVersion);
}
Compile it:
/usr/bin/clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/System/Library/Frameworks -x objective-c -o a.out -framework Foundation osversion.c
Then run it:
./a.out
It works fine and prints the OS version:
OS version: 14.6.1
Run it again and pass it some arbitrary program arguments:
./a.out foo bar
Still continues to work fine and prints the output:
OS version: 14.6.1
Now run it again and this time pass it two program arguments, the first one being - and the second one being something of the form {x=y}
./a.out - {x=y}
This time notice how it prints a couple of warning logs from CFPropertyListCreateFromXMLData before printing the output:
2024-10-11 11:18:03.584 a.out[61327:32412190] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
2024-10-11 11:18:03.585 a.out[61327:32412190] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
OS version: 14.6.1
As far as I can see there's nothing wrong in the code nor the user inputs to the program. Is this some issue in the internal implementation of NSProcessInfo? Should this be reported as an issue through feedback assistant (which category)?
Although this example was run on 14.6.1 of macos, the issue is reproducible on older versions too.
iOS 17
advertisementData:
{
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = CZL2;
kCBAdvDataRxPrimaryPHY = 1;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataServiceUUIDs = (
FFE0
);
kCBAdvDataTimestamp = "750419647.067132";
}
iOS 18
advertisementData:
{
kCBAdvDataIsConnectable = 0;
kCBAdvDataRxPrimaryPHY = 0;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataServiceUUIDs = (
FFE0
);
kCBAdvDataTimestamp = "750420105.457082";
}
What should I do if the key value pair of kCBAdvDataLocalName disappears?
Hi!
I would like try to boot the Linux kernel with the Hypervisor framework and see how far I get. So far the kernel runs up to the point where it's trying to identify the redistributor of the Hypervisor's GICv3, but I get an exception when it's reading the memory-mapped GICR_FIDR2 register. I tried the same via hv_gic_get_redistributor_reg() and get HV_DENIED.
What could be the reason for this exception? I believe I've initialized enough of the GIC for it to work. No interrupts yet, though.
It is of course entirely possible I forgot to set/clear some bits, but there are several redistributor registers missing in the framework, so it's not possible to do the full initialization a hardware GIC v3 implementation needs. I assume the Hypervisor's GIC abstraction takes care of several steps internally.
What are the steps to initialize the HVF's GIC? Do you have a working example? I couldn't find anything on the internet. The popular virtualization software out there all seem to bring their own emulated interrupt controller.
I'm using Sequoia 15.0.1.
Thank you for any hints!
The app crashes after the system Matter provisioning dialog disappears.
Fatal Exception: NSInvalidArgumentException
*** +[NSString stringWithUTF8String:]: NULL cString
Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x83f20 __exceptionPreprocess
1 libobjc.A.dylib 0x172b8 objc_exception_throw
2 Foundation 0x6194 +[NSString allocWithZone:]
3 Matter 0x471e30 MTRDeviceControllerStorageClasses
4 libsystem_dnssd.dylib 0x48ac CallbackWithError
5 libsystem_dnssd.dylib 0x2a10 DNSServiceProcessResult
6 libdispatch.dylib 0x3dd4 _dispatch_client_callout
7 libdispatch.dylib 0x72d8 _dispatch_continuation_pop
8 libdispatch.dylib 0x1b1c8 _dispatch_source_latch_and_call
9 libdispatch.dylib 0x19d8c _dispatch_source_invoke
10 libdispatch.dylib 0xb284 _dispatch_lane_serial_drain
11 libdispatch.dylib 0xbf64 _dispatch_lane_invoke
12 libdispatch.dylib 0x16cb4 _dispatch_root_queue_drain_deferred_wlh
13 libdispatch.dylib 0x16528 _dispatch_workloop_worker_thread
14 libsystem_pthread.dylib 0x4934 _pthread_wqthread
15 libsystem_pthread.dylib 0x10cc start_wqthread
A customer of mine reported that since updating to macOS 15 they aren't able to use my app anymore, which performs a deep scan of selected folders by recursively calling getattrlistbulk. The problem is that the app apparently keeps scanning forever, with the number of scanned files linearly increasing to infinity.
This happens for some folders on a SMB volume.
The customer confirmed that they can reproduce the issue with a small sample app that I attach below. At first, I created a sample app that only scans the contents of the selected folder without recursively scanning the subcontents, but the issue didn't happen anymore, so it seems to be related to recursively calling getattrlistbulk.
The output of the sample app on the customer's Mac is similar to this:
start scan /Volumes/shares/Backup/Documents level 0 fileManagerCount 2847
continue scan /Volumes/shares/Backup/Documents new items 8, sum 8, errno 34
/Volumes/shares/Backup/Documents/A.doc
/Volumes/shares/Backup/Documents/B.doc
...
continue scan /Volumes/shares/Backup/Documents new items 7, sum 1903, errno 0
/Volumes/shares/Backup/Documents/FKV.pdf
/Volumes/shares/Backup/Documents/KFW.doc
/Volumes/shares/Backup/Documents/A.doc
/Volumes/shares/Backup/Documents/B.doc
...
which shows that counting the number of files in the root folder by using
try FileManager.default.contentsOfDirectory(atPath: path).count
returns 2847, while getattrlistbulk lists about 1903 files and then starts listing the files from the beginning, not even between repeated calls, but within a single call.
What could this issue be caused by?
(The website won't let me attach .swift files, so I include the source code of the sample app as a text attachment.)
ViewController.swift
Our backup app (Arq) is encountering random errors for some users on macOS Sequoia.
The method [NSFileManager contentsOfDirectoryAtPath:error:] returns nil with an NSError domain NSCocoaErrorDomain, code 256 ("NSFileReadUnknownError").
The NSError's NSUnderlyingError key is an NSError with domain NSPOSIXErrorDomain and code 4 (EINTR).
Sometimes waiting and retrying works fine; sometimes 5 retries still fail.
For some users it happens on different directories each time they try to back up.
What is causing this? Are we supposed to use a different API to get directory contents these days?
Instead of using the MatterSupport framework to commission a device, I'd much rather throw the process over to the Home App if possible. I noticed that if I open my camera app and scan a Matter QR code, that starts the process to commission the device in the Home App. That means the Home App must be able to handle a url scheme with the QR code details. Is this available for developers to deep link into the Home App?
Launching the QR code as a url itself does not work so Apple Home isn't capturing the MT url scheme. Otherwise I can open Apple Home with com.apple.home:// but have no idea what params would need to be passed to that scheme.
if let url = URL(string: "MT:E9.01EEI141RUX5.210") {
UIApplication.shared.open(url) { result in print(result) }
}
Is there something in the documentation I'm missing that allows for this?