Explore the core architecture of the operating system, including the kernel, memory management, and process scheduling.

Post

Replies

Boosts

Views

Activity

CoreBluetooth writeValue:forCharacteristic:type: retains the data
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 ?
4
0
242
Oct ’24
FIFinderSyncController for ALL folders/files?
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]
5
0
234
Oct ’24
BLE Advertising
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) } } } }
2
0
218
Oct ’24
iOS security-scoped bookmark
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.
2
0
182
Oct ’24
How to Create an NFC-Enabled Wallet Pass with pass.json Including NFC Field?
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
2
0
337
Oct ’24
BLE Background Fetching - Polling vs. Notify
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?
1
0
148
Oct ’24
Bluetooth feature "extendedScanAndConnect" on iOS not supported at app start
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
1
0
170
Oct ’24
Reasonable time for fix to easy-to-reproduce kernel panic?
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?
0
0
224
Oct ’24
FileManager DirectoryEnumerator and skipDescendants issue
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)") } }
2
0
158
Oct ’24
Understanding `EINTR`
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.
0
0
107
Oct ’24
NSProcessInfo operatingSystemVersion generates warning CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary
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.
5
0
313
Oct ’24
IOS18 function centraliManager: didDiscoverPeripheral: advertising Data: RSSI The advertisement data does not have kCBAdDataLocalName.
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?
1
0
229
Oct ’24
Access denied to Hypervisor redistributor register
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!
3
0
233
Oct ’24
iOS 17.6.1 App crashes during Matter provisioning
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
0
0
149
Oct ’24
getattrlistbulk lists same files over and over on macOS 15 Sequoia
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
15
0
365
Oct ’24
NSFileManager contentsOfDirectoryAtPath:error: returns NSFileReadUnknownError with underlying POSIX EINTR
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?
1
0
256
Oct ’24
Can I hand Matter commissioning over to the Home App?
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?
2
0
262
Oct ’24