Processes & Concurrency

RSS for tag

Discover how the operating system manages multiple applications and processes simultaneously, ensuring smooth multitasking performance.

Concurrency Documentation

Posts under Processes & Concurrency subtopic

Post

Replies

Boosts

Views

Activity

Processes & Concurrency Resources
General: DevForums subtopic: App & System Services > Processes & Concurrency Processes & concurrency covers a number of different technologies: Background Tasks Resources Concurrency Resources — This includes Swift concurrency. Service Management Resources XPC Resources Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
145
Jul ’25
BGTaskScheduler crashes on iOS 18.4
I've been seeing a high number of BGTaskScheduler related crashes, all of them coming from iOS 18.4. I've encountered this myself once on launch upon installing my app, but haven't been able to reproduce it since, even after doing multiple relaunches and reinstalls. Crash report attached at the bottom of this post. I am not even able to symbolicate the reports despite having the archive on my MacBook: Does anyone know if this is an iOS 18.4 bug or am I doing something wrong when scheduling the task? Below is my code for scheduling the background task on the view that appears when my app launches: .onChange(of: scenePhase) { newPhase in if newPhase == .active { #if !os(macOS) let request = BGAppRefreshTaskRequest(identifier: "notifications") request.earliestBeginDate = Calendar.current.date(byAdding: .hour, value: 3, to: Date()) do { try BGTaskScheduler.shared.submit(request) Logger.notifications.log("Background task scheduled. Earliest begin date: \(request.earliestBeginDate?.description ?? "nil", privacy: .public)") } catch let error { // print("Scheduling Error \(error.localizedDescription)") Logger.notifications.error("Error scheduling background task: \(error.localizedDescription, privacy: .public)") } #endif ... } 2025-02-23_19-53-50.2294_+0000-876d2b8ec083447af883961da90398f00562f781.crash
33
8
3.6k
Apr ’25
Crash iOS 26 Beta
We are experiencing a crash in our application that only occurs on devices running iOS beta 26. It looks like a Beta problem. The crash appears to be caused by an excessive number of open File Descriptors. We identified this after noticing a series of crashes in different parts of the code each time the app was launched. Sometimes it would crash right at the beginning, when trying to load the Firebase plist file. That’s when we noticed a log message saying “too many open files,” and upon further investigation, we found that an excessive number of File Descriptors were open in our app, right after the didFinishLaunching method of the AppDelegate. We used the native Darwin library to log information about the FDs and collected the following: func logFDs() { var rlim = rlimit() if getrlimit(RLIMIT_NOFILE, &rlim) == 0 { print("FD LIMIT: soft: \(rlim.rlim_cur), hard: \(rlim.rlim_max)") } // Count open FDs before Firebase let openFDsBefore = countOpenFileDescriptors() print("Open file descriptors BEFORE Firebase.configure(): \(openFDsBefore)") } private func countOpenFileDescriptors() -> Int { var count = 0 let maxFD = getdtablesize() for fd in 0..<maxFD { if fcntl(fd, F_GETFD) != -1 { count += 1 } } return count } With this code, we obtained the following data: On a device with iOS 26 Beta 1, 2, or 3: FD LIMIT: soft: 256, hard: 9223372036854775807 Open file descriptors BEFORE Firebase.configure(): 256 On a device with iOS 18: FD LIMIT: soft: 256, hard: 9223372036854775807 Open file descriptors BEFORE Firebase.configure(): 57 In the case of the device running iOS 26 beta, the app crashes when executing Firebase.configure() because it cannot open the plist file, even though it can be found at the correct path — meaning the OS locates it. To confirm this was indeed the issue, we used the following code to close FDs before proceeding with Firebase configuration. By placing a breakpoint just before Firebase.configure() and running the following LLDB command: expr -l c -- for (int fd = 180; fd < 256; fd++) { (int)close(fd); } This released the FDs, allowing Firebase to proceed with its configuration as expected. However, the app would later crash again after hitting the soft limit of file descriptors once more. Digging deeper, we used this code to try to identify which FDs were being opened and causing the soft limit to be exceeded: func checkFDPath() { var r = rlimit() if getrlimit(RLIMIT_NOFILE, &r) == 0 { print("FD LIMIT: soft: \(r.rlim_cur), hard: \(r.rlim_max)") for fd in 0..<Int32(r.rlim_cur) { var path = [CChar](repeating: 0, count: Int(PATH_MAX)) if fcntl(fd, F_GETPATH, &path) != -1 { print(String(cString: path)) } } } } We ran this command at the very beginning of the didFinishLaunching method in the AppDelegate. On iOS 26, the log repeatedly showed Cryptexes creating a massive number of FDs, such as: /dev/null /dev/ttys000 /dev/ttys000 /private/var/mobile/Containers/Data/Application/AEE414F2-7D6F-44DF-A6D9-92EDD1D2B014/Library/Application Support/DTX_8.191.1.1003.sqlite /private/var/mobile/Containers/Data/Application/AEE414F2-7D6F-44DF-A6D9-92EDD1D2B014/Library/Caches/KSCrash/MyAppScheme/Data/ConsoleLog.txt /private/var/mobile/Containers/Data/Application/AEE414F2-7D6F-44DF-A6D9-92EDD1D2B014/Library/HTTPStorages/mybundleId/httpstorages.sqlite /private/var/mobile/Containers/Data/Application/AEE414F2-7D6F-44DF-A6D9-92EDD1D2B014/Library/HTTPStorages/mybundleId/httpstorages.sqlite-wal /private/var/mobile/Containers/Data/Application/AEE414F2-7D6F-44DF-A6D9-92EDD1D2B014/Library/HTTPStorages/mybundleId/httpstorages.sqlite-shm /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.01 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.11 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.12 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.13 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.14 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.15 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.16 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.17 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.18 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.19 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.20 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.21 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.22 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.23 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.24 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.25 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.26 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.29 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.30 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.31 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.32 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.36 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.37 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.38 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.39 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.40 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e … This repeats itself a lot of times. … /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.36 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.37 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.38 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.39 /private/preboot/Cryptexes/OS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e.40
3
8
297
Jul ’25
Crashes because main actor isolated closures are called on a background thread with `DispatchGroup.notify`, but no compiler warnings
Hello! We are in the progress of migrating a large Swift 5.10 legacy code base over to use Swift 6.0 with Strict Concurrency checking. We have already stumbled across a few weird edge cases where the "guaranteed" @MainActor isolation is violated (such as with @objc #selector methods used with NotificationCenter). However, we recently found a new scenario where our app crashes accessing main actor isolated state on a background thread, and it was surprising that the compiler couldn't warn us. Minimal reproducible example: class ViewController: UIViewController { var isolatedStateString = "Some main actor isolated state" override func viewDidLoad() { exampleMethod() } /// Note: A `@MainActor` isolated method in a `@MainActor` isolated class. func exampleMethod() { testAsyncMethod() { [weak self] in // !!! Crash !!! MainActor.assertIsolated() // This callback inherits @MainActor from the class definition, but it is called on a background thread. // It is an error to mutate main actor isolated state off the main thread... self?.isolatedStateString = "Let me mutate my isolated state" } } func testAsyncMethod(completionHandler: (@escaping () -> Void)) { let group = DispatchGroup() let queue = DispatchQueue.global() // The compiler is totally fine with calling this on a background thread. group.notify(queue: queue) { completionHandler() } // The below code at least gives us a compiler warning to add `@Sendable` to our closure argument, which is helpful. // DispatchQueue.global().async { // completionHandler() // } } } The problem: In the above code, the completionHandler implementation inherits main actor isolation from the UIViewController class. However, when we call exampleMethod(), we crash because the completionHandler is called on a background thread via the DispatchGroup.notify(queue:). If were to instead use DispatchQueue.global().async (snippet at the bottom of the sample), the compiler helpfully warns us that completionHandler must be Sendable. Unfortunately, DispatchGroup's notify gives us no such compiler warnings. Thus, we crash at runtime. So my questions are: Why can't the compiler warn us about a potential problem with DispatchGroup().notify(queue:) like it can with DispatchQueue.global().async? How can we address this problem in a holistic way in our app, as it's a very simple mistake to make (with very bad consequences) while we migrate off GCD? I'm sure the broader answer here is "don't mix GCD and Concurrency", but unfortunately that's a little unavoidable as we migrate our large legacy code base! 🙂
3
3
429
2w
ExtensionKit and iOS 26
It looks like ExtensionKit (and ExtensionFoundation) is fully available on iOS 26 but there is no mention about this in WWDC. From my testing, it seems as of beta 1, ExtensionKit allows the app from one dev team to launch extension provided by another dev team. Before we start building on this, can someone from Apple help confirm this is the intentional behavior and not just beta 1 thing?
1
4
211
Jun ’25
How to Get Client Process Owner in an XPC Server
I'm working on an XPC server and need to determine the owner of the client process that connects to it. Specifically, I'd like to retrieve details such as the fully qualified user name or other identifying information from the XPC client connection.I'm considering using xpc_connection_get_pid() to get the client’s process ID, but I’m unsure of the best way to map this to the user who owns the process. Is there a recommended API or approach to capture this information securely?
1
3
208
Mar ’25
XCode 26.0.1/iOS 26 unable to mark class as ObservableObject
Started a new X-Code Project after updating to 26.0.1 and realized that I get an error when trying to mark a class as ObservableObject => "Class XYZ does not conform to Protocol 'ObservableObject'. Strange behaviour, because at old projects the code is working even though the build options are the same and other settings like iOS version in Target are the same. There must be something chaged under the hood of XCode? I have to import Combine now, before I could write my class, e.g. CoreData Datamanager: ObservableObject only using CoreData.
4
0
301
Oct ’25
Privileged helper without SMJobBless
To establish a privileged helper daemon from a command line app to handle actions requiring root privileges I still use the old way of SMJobBless. But this is deprecated since OSX 10.13 and I want to finally update it to the new way using SMAppService. As I'm concerned with securing it against malicious exploits, do you have a recommended up-to-date implementation in Objective-C establishing a privileged helper and verifying it is only used by my signed app? I've seen the suggestion in the documentation to use SMAppService, but couldn't find a good implementation covering security aspects. My old implementation in brief is as follows: bool runJobBless () { // check if already installed NSFileManager* filemgr = [NSFileManager defaultManager]; if ([filemgr fileExistsAtPath:@"/Library/PrivilegedHelperTools/com.company.Helper"] && [filemgr fileExistsAtPath:@"/Library/LaunchDaemons/com.company.Helper.plist"]) { // check helper version to match the client // ... return true; } // create authorization reference AuthorizationRef authRef; OSStatus status = AuthorizationCreate (NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef); if (status != errAuthorizationSuccess) return false; // obtain rights to install privileged helper AuthorizationItem authItem = { kSMRightBlessPrivilegedHelper, 0, NULL, 0 }; AuthorizationRights authRights = { 1, &authItem }; AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; status = AuthorizationCopyRights (authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL); if (status != errAuthorizationSuccess) return false; // SMJobBless does it all: verify helper against app and vice-versa, place and load embedded launchd.plist in /Library/LaunchDaemons, place executable in /Library/PrivilegedHelperTools CFErrorRef cfError; if (!SMJobBless (kSMDomainSystemLaunchd, (CFStringRef)@"com.company.Helper", authRef, &cfError)) { // check helper version to match the client // ... return true; } else { CFBridgingRelease (cfError); return false; } } void connectToHelper () { // connect to helper via XPC NSXPCConnection* c = [[NSXPCConnection alloc] initWithMachServiceName:@"com.company.Helper.mach" options:NSXPCConnectionPrivileged]; c.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol (SilentInstallHelperProtocol)]; [c resume]; // call function on helper and wait for completion dispatch_semaphore_t semaphore = dispatch_semaphore_create (0); [[c remoteObjectProxy] callFunction:^() { dispatch_semaphore_signal (semaphore); }]; dispatch_semaphore_wait (semaphore, dispatch_time (DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC)); dispatch_release (semaphore); [c invalidate]; [c release]; }
3
0
166
Oct ’25
macOS 26: Menu bar icon not showing for Python app running PySide6
Since macOS 26, including the latest 26.1, the menu bar icon does not show up for our app called Plover which is built with PySide6 (based on Qt 6) and runs via a relocatable python that is packaged into the app. The code is open source and can be found on GitHub. The latest release, including the notarized DMG, can be found here. When running the .app via the command below, the menu bar icon does show up but the process that is running is python3.13 and not Plover: /Applications/Plover.app/Contents/MacOS/Plover -l debug When running the app by just clicking on the application icon, the process is Plover but the menu bar icon is not showing - also not in the settings (Menu Bar > Allow in the Menu Bar). Before macOS 26, the menu bar icon was always shown. Some pointers to potentially relevant parts of our code: shell script that builds the .app Info.plist plover_launcher.c trayicon.py This problem might be related to this thread, including the discussion around Qt not calling NSApplicationMain. What I'm trying to figure out is whether this is a problem with macOS 26, Qt 6, PySide6, or our code. Any pointers are highly appreciated!
7
0
251
1w
Persistent font registration crashes when fonts are delivered via Apple-Hosted Background Assets
Hi everyone, I’m trying to register fonts system-wide using CTFontManagerRegisterFontURLs with the .persistent scope. The fonts are delivered through Apple-Hosted Background Assets (since On-Demand Resources are deprecated). Process-level registration works perfectly, but persistent registration triggers a system “Install Fonts” prompt, and tapping Install causes the app to crash immediately. I’m wondering if anyone has successfully used Apple-Hosted Background Assets to provide persistent, system-wide installable fonts, or if this is a current OS limitation/bug. What I Expect Fonts delivered through Apple-Hosted Background Assets should be eligible for system-wide installation Tap “Install” should install fonts into Settings → Fonts just like app-bundled or ODR fonts App should not crash Why This Matters According to: WWDC 2019: Font Management and Text Scaling Developers can build font provider apps that install fonts system-wide, using bundled or On-Demand Resources. WWDC 2025: Discover Apple-Hosted Background Assets On-Demand Resources are deprecated, and AHBAs are the modern replacement. Therefore, persistent font installation via Apple-Hosted Background Assets appears to be the intended path moving forward. Question Is this a known limitation or bug in iOS? Should .persistent font installation work with Apple-Hosted Background Assets? Do we need additional entitlement, manifest configuration, or packaging rules? Any guidance or confirmation from Apple engineers would be greatly appreciated. Additional Info I submitted a Feedback including a minimal reproducible sample project: FB21109320
3
0
137
2d
Phone unlock/lock detection
Hi, I'll explain my question through how whatsapp does it. When the phone is locked then whatsapp routes call through apple's native callkit When unlocked, pressing accept essentially redirects to whatsapp and then whatsapp handles the call from there. However, this component of unlock detection is what I'm not able to find any info about. Essentially, how i do it is: let isPhoneLocked = !UIApplication.shared.isProtectedDataAvailable isProtectedDataAvailable == true → device is unlocked isProtectedDataAvailable == false → device is locked The problem is that if the phone has been recently unlocked, then protected data is still available on the phone even after the lock for the next 10-40 seconds. So theres a false positive. I want there to be a foolproof and robust way to do this. And I'm not entirely sure how
3
0
72
4d
In the context of Live Activity, when app is launched into background due to some callback, should you wrap your work with background tasks?
I'm specifically focused on Live Activity, but I think this is somewhat a general question. The app could get a few callbacks when: There's a new payload (start, update, end) There's a new token (start, update) There's some other lifecycle event (stale, dismissed) Assuming that the user didn't force kill the app, would the app get launched in all these scenarios? When OS launches the app for a reason, should we wrap our tasks with beginBackgroundTask or that's unnecessary if we're expecting our tasks to finish within 30 seconds? Or the OS may sometimes be under stress and give you far less time (example 3 seconds) and if you're in slow internet, then adding beginBackgroundTask may actually come in handy?
2
0
47
1w
EXC_BREAKPOINT in BGAppRefreshTask
When I run my app with XCode on my iPhone, and then moved into the background, I'm getting a EXC_BREAKPOINT exception after a few minutes, seemingly when iOS attempts to call my app with a BGAppRefreshTask: Thread 23 Queue: com.apple.BGTaskScheduler (com.mycompany.MyApp.RefreshTask) (serial) 0 _dispatch_assert_queue_fail 12 _pthread_wqthread Enqueued from com.apple.duet.activityscheduler.client.xpcqueue (Thread 23) 0 dispatch_async 20 start_wqthread I can't quite understand the reason from this crash. In the background task, I'm attempting to update live activities. In the process, it might encounter code that calls MainActor and manipulate @Observable objects. Might that be the reason?
2
1
452
Feb ’25
Testing XPC Code With an Anonymous Listener using Low Level C APIs
I have implemented a XPC server using C APIs. I want to write unit tests for it. I came across the following links that use Swift APIs- Testing and Debugging XPC Code With an Anonymous Listener TN3113 I have tried to write anonymous listener code and the client code in the same file, using C APIs- #include <unistd.h> #include <syslog.h> #include <pthread.h> #include <stdio.h> #include <xpc/xpc.h> #include <xpc/connection.h> #include <CoreFoundation/CoreFoundation.h> static void Anon_Client_Connection_Handler(xpc_connection_t connection, xpc_object_t clientMessage) { const char *description = xpc_copy_description(clientMessage); printf("Event received - %s\n", description); free((void *)description); xpc_type_t type = xpc_get_type(clientMessage); if (type == XPC_TYPE_ERROR) { if (clientMessage == XPC_ERROR_CONNECTION_INVALID) printf("Client_Connection_Handler received invalid connection n"); else if (clientMessage == XPC_ERROR_TERMINATION_IMMINENT) printf("Client_Connection_Handler received termination notice n"); } else { const char *clientMsg = xpc_dictionary_get_string(clientMessage, "message"); printf("Received from client: %s ", clientMsg); } } static void Anon_Listener_Connection_Handler(xpc_connection_t connection) { printf("Anon_Listener_Connection_Handler called, setting up event handler \n"); xpc_connection_set_event_handler(connection, ^(xpc_object_t clientMessage) { printf("Processing the connection! \n"); Anon_Client_Connection_Handler(connection, clientMessage); }); xpc_connection_resume(connection); } int main(int argc, const char *argv[]) { xpc_connection_t anon_listener = xpc_connection_create(NULL, NULL); xpc_connection_set_event_handler(anon_listener, ^(xpc_object_t clientConnection) { printf("Client tried to connect \n"); Anon_Listener_Connection_Handler(clientConnection); }); xpc_connection_resume(anon_listener); printf("\nINFO Anonymous connection resumed"); xpc_object_t anon_endpoint = xpc_endpoint_create(anon_listener); xpc_connection_t clientConnection = xpc_connection_create_from_endpoint(anon_endpoint); xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_string(message, "message", "client's message"); xpc_connection_send_message_with_reply(clientConnection, message, dispatch_get_main_queue(), ^(xpc_object_t event) { printf("\nINFO inside reply"); const char *description = xpc_copy_description(event); printf("\nINFO %s",description); free((void *)description); }); xpc_release(message); xpc_release(anon_listener); printf("\nINFO Releasing listener"); xpc_release(anon_endpoint); printf("\nINFO Releasing endpoint"); // dispatch_main(); return 0; } and this is the output I get INFO Anonymous connection resumed INFO Releasing listener INFO Releasing endpoint I am not able to connect to the client and exchange messages. Where am I going wrong?
1
1
352
Mar ’25
What is the new name of the OSDUIHelper process on macOS Tahoe?
I am currently developing a macOS app that can show system HUDs in the Notch Till Sequoia I used to kill the OSDUIHelper process (which displays the default macOS Volume and Brightness control HUDs) - and replaced it with my app's HUDs But, it is not working on macOS Tahoe anymore as the OSDUIHelper process is no longer there due to the UI changes Has the process been renamed - or is there any other way to kill the process?
1
0
89
Oct ’25
Stay connected to Medical BLE device in background
I work for a large medical device company. We have a 1st party BLE enabled medical device that must be very battery efficient. To this end, if a connection is lost, the BLE radio is powered down after 60 seconds and will only turn back on when a physical button on the device is pressed. I've been tasked with connecting to the device, staying connected to the device, and being able to retrieve data from the device upon a timed action. For instance, this could include a data read and transmission while they sleep. The key part of this is staying reliably connected for extended periods of time. This is a BYOD setup, and we cannot control power profiles. I would very much appreciate any information, recommendations, and/or insights into solving this problem. Thanks!
1
0
323
Sep ’25
Keeping a socket connection active in app extension in a Safari Web Extension
I’m currently porting a Chrome Extension to Safari and integrating it with native messaging in a Safari Web Extension. As part of this, I’m building a proxy to forward messages between the web extension and a socket in another application, both ways. Additionally, the socket occasionally broadcasts messages that also need to be sent to the web extension. The issue I’m facing is that the app extension terminates whenever I call context.completeRequest(returningItems: nil), which prevents me from listening for incoming messages from the socket (I'm using the Network Framework). To work around this, I’ve tried not calling context.completeRequest(returningItems: nil), which keeps the app extension running. However, I’m unsure if this is the right approach—currently, I’m simply ignoring the response and relying entirely on SFSafariApplication.dispatchMessage. According to the documentation, the app extension lifecycle ends when the system terminates it, but I need to keep the socket listener active. Has anyone encountered a similar issue, or does anyone have suggestions for maintaining the socket connection while adhering to the app extension lifecycle? Any insights would be greatly appreciated!
2
0
494
Jan ’25
How to detect or opt out of iOS app prewarming?
Hi, We are running into issues with iOS app prewarming, where the system launches our app before the user has entered their passcode. In our case, the app stores flags, counters, and session data in UserDefaults and the Keychain. During prewarm launches: UserDefaults only returns default values (nil, 0, false). We have no way of knowing whether this information is valid or just a placeholder caused by prewarming. Keychain items with kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly are inaccessible, which can lead to broken business logic (the app can assume no session exists). No special launch options or environment variables appear to be set. We can reproduce this 100% of the time by starting a Live Activity in the app before reboot. Here’s an example of the workaround we tried, following older recommendations: __attribute__((constructor)) static void ModuleInitializer(void) { char* isPrewarm = getenv("ActivePrewarm"); if (isPrewarm != NULL && isPrewarm[0] == '1') { exit(0); // prevent prewarm launch from proceeding } } On iOS 16+, the ActivePrewarm environment variable doesn’t seem to exist anymore (though older docs and SDKs such as Sentry reference it). We also tried listening for UIApplication.protectedDataDidBecomeAvailableNotification, but this is not specific to prewarming (it also fires when the device gets unlocked) and can cause watchdog termination if we delay work too long. Questions: Is there a supported way to opt out of app prewarming? What is the correct way to detect when an app is being prewarmed? Is the ActivePrewarm environment variable still supported in iOS 16+? Ideally, the UserDefaults API itself should indicate whether it is returning valid stored values or defaults due to the app being launched in a prewarm session. We understand opting out may impact performance, but data security and integrity are our priority. Any guidance would be greatly appreciated.
1
0
145
Oct ’25
Does Mac Catalyst support Background Processing?
I have an app for macOS that is built using Mac Catalyst. I need to perform some background processing. I'm using BGProcessingTaskRequest to schedule the request. I have also integrated CKSyncEngine so I need that to be able to perform its normal background processing. On iOS, when the user leaves the app, I can see a log message that the request was scheduled and a bit later I see log messages coming from the actual background task code. On macOS I ran the app from Xcode. I then quit the app (Cmd-q). I can see the log message that the request was scheduled. But the actual task is never run. In my test, I ran my app on a MacBook Pro running macOS 26.0. When I quit the app, I checked the log file in the app sandbox and saw the message that the task was scheduled. About 20 minutes later I closed the lid on the MacBook Pro for the night. I did not power down, it just went to sleep. Roughly 10 hours later I opened the lid on the MacBook Pro, logged in, and checked the log file. It had not been updated since quitting the app. I should also mention that the laptop was not plugged in at all during this period. My question is, does a Mac Catalyst app support background processing after the user quits the app? If so, how is it enabled? The documentation for BGProcessingTaskRequest and BGProcessingTask show they are supported under Mac Catalyst, but I couldn't find any documentation in the Background Tasks section that mentioned anything specific to setup for Mac Catalyst. Running the Settings app and going to General -> Login Items & Extension, I do not see my app under the App Background Activity section. Does it need to be listed there? If so, what steps are needed to get it there? If this is all documented somewhere, I'd appreciate a link since I was not able to find anything specific to making this work under Mac Catalyst.
4
1
94
2d
App Terminated with 0x8BADF00D: Main Thread Blocked During Back-to-Back Messaging
Hello, I'm experiencing an issue with my app where it's being terminated by the system with a watchdog violation during back-to-back messaging operations. I've analyzed the crash logs but would appreciate additional insights on optimizing my approach. I'd appreciate any insights on how to resolve this problem. Crash Details: Exception Type: EXC_CRASH (SIGKILL) Termination Reason: FRONTBOARD with code 0x8BADF00D Error: "scene-update watchdog transgression: app exhausted real time allowance of 10.00 seconds" Reproduction Steps: User A initiates back-to-back messages to other User User A's UI becomes unresponsive and eventually the app crashes. Stack Trace Analysis: The crash occurs on the main thread, which appears to be blocked waiting for a condition in the keyboard handling system. The thread is stuck in [UIKeyboardTaskQueue _lockWhenReadyForMainThread] and related methods, suggesting an issue with keyboard-related operations during the messaging process. Crash Tag Exception Type: EXC_CRASH (SIGKILL) Exception Codes: 0x0000000000000000, 0x0000000000000000 Termination Reason: FRONTBOARD 2343432205 <RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: app<com.msikodiak.eptt(AD934F8A-DF57-4B75-BE73-8CF1A9A8F856)>:301 exhausted real (wall clock) time allowance of 10.00 seconds ProcessVisibility: Foreground ProcessState: Running WatchdogEvent: scene-update WatchdogVisibility: Background WatchdogCPUStatistics: ( "Elapsed total CPU time (seconds): 6.390 (user 3.640, system 2.750), 11% CPU", "Elapsed application CPU time (seconds): 0.020, 0% CPU" ) ThermalInfo: ( "Thermal Level: 0", "Thermal State: nominal" ) reportType:CrashLog maxTerminationResistance:Interactive> Triggered by Thread: 0 Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libsystem_kernel.dylib 0x1e773d438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x2210bc328 _pthread_cond_wait + 1028 2 Foundation 0x1957d8a64 -[NSCondition waitUntilDate:] + 132 3 Foundation 0x1957d8888 -[NSConditionLock lockWhenCondition:beforeDate:] + 80 4 UIKitCore 0x1998f1238 -[UIKeyboardTaskQueue _lockWhenReadyForMainThread] + 456 5 UIKitCore 0x19a3d775c __59-[UIKeyboardImpl updateAutocorrectPrompt:executionContext:]_block_invoke_9 + 28 6 UIKitCore 0x19986b084 -[UIKeyboardTaskQueue lockWhenReadyForMainThread] + 168 7 UIKitCore 0x19a3f2994 -[UIKeyboardTaskQueue waitUntilTaskIsFinished:] + 148 8 UIKitCore 0x19a3f2ac4 -[UIKeyboardTaskQueue performSingleTask:breadcrumb:] + 132 9 UIKitCore 0x199e2f7e4 -[_UIKeyboardStateManager updateForChangedSelection] + 144 10 UIKitCore 0x199e24200 -[_UIKeyboardStateManager invalidateTextEntryContextForTextInput:] + 92 11 WebKit 0x1ad52fa54 WebKit::PageClientImpl::didProgrammaticallyClearFocusedElement(WebCore::ElementContext&&) + 40 12 WebKit 0x1ad55adcc WebKit::WebPageProxy::didProgrammaticallyClearFocusedElement(WebCore::ElementContext&&) + 136 13 WebKit 0x1acec74e8 WebKit::WebPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 18604 14 WebKit 0x1acd21184 IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 236 15 WebKit 0x1ace449b8 WebKit::WebProcessProxy::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 40 16 WebKit 0x1ace44228 WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 1764 17 WebKit 0x1acd1e904 IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 268 18 WebKit 0x1acd1e478 IPC::Connection::dispatchIncomingMessages() + 576 19 JavaScriptCore 0x1ae386b8c WTF::RunLoop::performWork() + 524 20 JavaScriptCore 0x1ae386960 WTF::RunLoop::performWork(void*) + 36 21 CoreFoundation 0x196badce4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 22 CoreFoundation 0x196badc78 __CFRunLoopDoSource0 + 172 23 CoreFoundation 0x196bac9fc __CFRunLoopDoSources0 + 232 24 CoreFoundation 0x196babc3c __CFRunLoopRun + 840 25 CoreFoundation 0x196bd0700 CFRunLoopRunSpecific + 572 26 GraphicsServices 0x1e3711190 GSEventRunModal + 168 27 UIKitCore 0x1997ee240 -[UIApplication _run] + 816 28 UIKitCore 0x1997ec470 UIApplicationMain + 336 29 Telstra PTT 0x1004d30c8 main + 56 30 dyld 0x1bd5d3ad8 start + 5964
4
1
286
Oct ’25