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

XPC codesign requirement crashes application
We have an application that sets a code signing requirement on a XPC connection between a File Provider extension and the main application. Only with a specific Developer ID certificate <DEVELOPER_ID_TEAM_IDENTIFIER> that designated requirement is not accepted and the application crashes with EXC_CRASH (SIGABRT) and the stacktrace Thread 1 Crashed:: Dispatch queue: com.apple.root.default-qos 0 libsystem_kernel.dylib 0x19b556388 __pthread_kill + 8 1 libsystem_pthread.dylib 0x19b58f88c pthread_kill + 296 2 libsystem_c.dylib 0x19b498a3c abort + 124 3 libc++abi.dylib 0x19b545384 abort_message + 132 4 libc++abi.dylib 0x19b533cf4 demangling_terminate_handler() + 344 5 libobjc.A.dylib 0x19b1b8dd4 _objc_terminate() + 156 6 libc++abi.dylib 0x19b544698 std::__terminate(void (*)()) + 16 7 libc++abi.dylib 0x19b547c30 __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88 8 libc++abi.dylib 0x19b547bd8 __cxa_throw + 92 9 libobjc.A.dylib 0x19b1aecf8 objc_exception_throw + 448 10 Foundation 0x19d5c3840 -[NSXPCConnection setCodeSigningRequirement:] + 140 11 libxpcfileprovider.dylib 0x301023048 NSXPCConnection.setCodeSigningRequirementFromTeamIdentifier(_:) + 1796 12 libxpcfileprovider.dylib 0x30101dc94 closure #1 in CallbackFileProviderManager.getFileProviderConnection(_:service:completionHandler:interruptionHandler:exportedObject:) + 1936 13 libxpcfileprovider.dylib 0x30101e110 thunk for @escaping @callee_guaranteed @Sendable (@guaranteed NSXPCConnection?, @guaranteed Error?) -> () + 80 14 Foundation 0x19d46c3a4 __72-[NSFileProviderService getFileProviderConnectionWithCompletionHandler:]_block_invoke_2.687 + 284 15 libdispatch.dylib 0x19b3d7b2c _dispatch_call_block_and_release + 32 16 libdispatch.dylib 0x19b3f185c _dispatch_client_callout + 16 17 libdispatch.dylib 0x19b40e490 + 32 18 libdispatch.dylib 0x19b3e9fa4 _dispatch_root_queue_drain + 736 19 libdispatch.dylib 0x19b3ea5d4 _dispatch_worker_thread2 + 156 20 libsystem_pthread.dylib 0x19b58be28 _pthread_wqthread + 232 21 libsystem_pthread.dylib 0x19b58ab74 start_wqthread + 8 The designated codesign requirement on the XPC connection is set to anchor apple generic and certificate leaf[subject.OU] = <DEVELOPER_ID_TEAM_IDENTIFIER>" We have verified the designated code sign requirement to be valid on both the main bundle and the embedded extension using: codesign --verify -v -R '=anchor apple generic and certificate leaf[subject.OU] = "<DEVELOPER_ID_TEAM_IDENTIFIER>"' *.app codesign --verify -v -R '=anchor apple generic and certificate leaf[subject.OU] = "<DEVELOPER_ID_TEAM_IDENTIFIER>"' *.app/Contents/PlugIns/*
2
0
336
Sep ’25
Background Task Scheduler
Hello, An application I am working on would like to schedule push notifications for a medication reminder app. I am trying to use BGTaskScheduler to wake up periodically and submit the notifications based on the user's medication schedule. I set up the task registration in my AppDelegate's didFinishLaunchingWithOptions method: BGTaskScheduler.shared.register( forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in self.scheduleNotifications() task.setTaskCompleted(success: true) self.scheduleAppRefresh() } scheduleAppRefresh() I then schedule the task using: func scheduleAppRefresh() { let request = BGAppRefreshTaskRequest(identifier: backgroundTaskIdentifier) request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 1) do { try BGTaskScheduler.shared.submit(request) } catch { } } In my testing, I can see the background task getting called once, but if I do not launch the application during the day. The background task does not get called the next day. Is there something else I need to add to get repeated calls from the BGTaskScheduler? Thank You, JR
2
0
237
Oct ’25
SSO Extension Fails XPC Connection to System Daemon (mach-lookup exception used)
Hello, I'm running into an issue with a complex macOS application (non-AppStore) structure involving an unsandboxed system daemon and a sandboxed SSO Extension attempting to communicate via XPC Mach service. The macOS app is composed of three main components: Main App: unsandboxed, standard macOS application. System Daemon: unsandboxed executable installed with a .plist to /Library/LaunchDaemons/ and loaded by launchd. It exposes an XPC Mach Service. SSO Extension: a sandboxed Authentication Services Extension (ASAuthorizationProviderExtension). Main App to System Daemon communication works perfectly. The unsandboxed main app can successfully create and use an XPC connection to the System Daemon's Mach service. But SSO Extension cannot establish an XPC connection to the System Daemon's Mach service, despite using the recommended temporary exception entitlement. I have added the following entitlement to the SSO Extension's entitlements file: <key>com.apple.security.temporary-exception.mach-lookup.global-name</key> <array> <string>my.xpc.service.system.daemon</string> </array> (The name my.xpc.service.system.daemon is the exact name registered by the System Daemon in its Launch Daemon plist's MachServices dictionary.) When the SSO Extension attempts to create the connection, the following log output is generated: default 08:11:58.531567-0700 SSOExtension [0x13f19b090] activating connection: mach=true listener=false peer=false name=my.xpc.service.system.daemon default 08:11:58.532150-0700 smd [0xb100d8140] activating connection: mach=false listener=false peer=true name=com.apple.xpc.smd.peer[1575].0xb100d8140 error 08:11:58.532613-0700 smd Item real path failed. Maybe the item has been deleted? error 08:11:58.532711-0700 SSOExtension Unable to find service status () error: 22 The error Unable to find service status () error: 22. Error code 22 typically translates to EINVAL (Invalid argument), but in this context, it seems related to the system's ability to find and activate the service for the sandboxed process. Questions: Is the com.apple.security.temporary-exception.mach-lookup.global-name entitlement sufficient for a sandboxed SSO Extension to look up a system-wide Launch Daemon Mach service, or are there additional restrictions or required entitlements for extensions? The smd log output Item real path failed. Maybe the item has been deleted? seems concerning. Since the unsandboxed main app can connect, this suggests the service is running and registered. Could this error indicate a sandbox permission issue preventing smd from verifying the path for the sandboxed process? Are there specific sandboxing requirements for Mach service names when communicating from an Extension versus a main application? Any guidance on how a sandboxed SSO Extension can reliably connect to an unsandboxed, non-app-group-related system daemon via XPC Mach service would be greatly appreciated!
2
0
242
Oct ’25
How to view documentation and example codes for Grand Central Dispatch for C
Hi, I am programming in C and would like to use Grand Central Dispatch for parallel computing (I mostly do physics based simulations). I remember there used to be example codes provided by Apple, but can't find those now. Instead I get the plain documentation. May anyone point me to the correct resources? It will be greatly appreciated. Thanks ☺.
2
0
296
Oct ’25
Bluetooth work with BGTaskScheduler
Hi All, I'm working on an app that needs to connect to BLE device and on defined schedules download data from the device. the amount of data is segnificant and might take around a minute to download. we tought about utilizing both state restoration and preservation for app waking and scheduling (triggered by the ble peripheral) and BGTaskScheduler to schedule a task that will handle a long running task to manage the full data download. now, will this solution in general valid? isnt it a "hack" that goes around the 10s limit that state restoration enforces? i know there are limitations for BGTask (like when it runs, it might be terminated by the system etc) but considering that, can we proceed with this approach without breaching apple guidelines? thank you in advance!
2
0
208
Oct ’25
BGContinuedProcessingTask UI
When I use BGContinuedProcessingTask to submit a task, my iPhone 12 immediately shows a notification banner displaying the task’s progress. However, on my iPhone 15 Pro Max, there’s no response — the progress UI only appears in the Dynamic Island after I background the app. Why is there a difference in behavior between these two devices? Is it possible to control the UI so that the progress indicator only appears when the app moves to the background?
2
0
311
Oct ’25
How to safely terminate hanging threads in launched agent context
Hello, In a launched agent, I need to call into a third‑party library that may occasionally hang. At present, these calls are made from a separate thread, but if the thread hangs it cannot be terminated (pthread_cancel/pthread_kill are ineffective). Would Apple recommend isolating this functionality in a separate process that can be force‑terminated if it becomes unresponsive, or is there a preferred approach for handling such cases in launched agents? Can I use the system call fork() in launched agent? Thank you in advance!
2
0
152
Oct ’25
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
362
Jan ’26
NotificationCenter.notifications(named:) appears to buffer internally and can drop notifications, but is this documented anywhere?
I've experimentally seen that the notifications(named:) API of NotificationCenter appears to buffer observed notifications internally. In local testing it appears to be limited to 8 messages. I've been unable to find any documentation of this fact, and the behavior seems like it could lead to software bugs if code is not expecting notifications to potentially be dropped. Is this behavior expected and documented somewhere? Here is a sample program demonstrating the behavioral difference between the Combine and AsyncSequence-based notification observations: @Test nonisolated func testNotificationRace() async throws { let testName = Notification.Name("TestNotification") let notificationCount = 100 var observedAsyncIDs = [Int]() var observedCombineIDs = [Int]() let subscribe = Task { @MainActor in print("setting up observer...") let token = NotificationCenter.default.publisher(for: testName) .sink { value in let id = value.userInfo?["id"] as! Int observedCombineIDs.append(id) print("🚜 observed note with id: \(id)") } defer { extendLifetime(token) } for await note in NotificationCenter.default.notifications(named: testName) { let id: Int = note.userInfo?["id"] as! Int print("🚰 observed note with id: \(id)") observedAsyncIDs.append(id) if id == notificationCount { break } } } let post = Task { @MainActor in for i in 1...notificationCount { NotificationCenter.default.post( name: testName, object: nil, userInfo: ["id": i] ) } } _ = await (post.value, subscribe.value) #expect(observedAsyncIDs.count == notificationCount) // 🛑 Expectation failed: (observedAsyncIDs.count → 8) == (notificationCount → 100) #expect(observedCombineIDs == Array(1...notificationCount)) print("done") }
2
0
292
Dec ’25
Flutter library that basically makes a call every "x" minutes if the app is in the background.
Hi everyone, could you help us? We implemented a Flutter library that basically makes a call every x minutes if the app is in the background, but when I generate the version via TestFlight for testing, it doesn't work. Can you help us understand why? Below is a more detailed technical description. Apple Developer Technical Support Request Subject: BGTaskScheduler / Background Tasks Not Executing in TestFlight - Flutter App with workmanager Plugin Issue Summary Background tasks scheduled using BGTaskScheduler are not executing when the app is distributed via TestFlight. The same implementation works correctly when running the app locally via USB/Xcode debugging. We are developing a Flutter application that needs to perform periodic API calls when the app is in the background. We have followed all documentation and implemented the required configurations, but background tasks are not being executed in the TestFlight build. App Information Field Value App Version 3.1.15 (Build 311) iOS Minimum Deployment Target iOS 15.0 Framework Flutter Flutter SDK Version ^3.7.2 Technical Environment Flutter Dependencies (Background Task Related) Package Version Purpose workmanager ^0.9.0+3 Main background task scheduler (uses BGTaskScheduler on iOS 13+) flutter_background_service ^5.0.5 Background service management flutter_background_service_android ^6.2.4 Android-specific background service flutter_local_notifications ^19.4.2 Local notifications for background alerts timezone ^0.10.0 Timezone support for scheduling Other Relevant Flutter Dependencies Package Version firebase_core 4.0.0 firebase_messaging (via native Podfile) sfmc (Salesforce Marketing Cloud) ^9.0.0 geolocator ^14.0.0 permission_handler ^12.0.0+1 Info.plist Configuration We have added the following configurations to Info.plist: UIBackgroundModes <key>UIBackgroundModes</key> <array> <string>location</string> <string>remote-notification</string> <string>processing</string> </array> ### BGTaskSchedulerPermittedIdentifiers ```xml <key>BGTaskSchedulerPermittedIdentifiers</key> <array> <string>br.com.unidas.apprac.ios.workmanager.carrinho_api_task</string> <string>br.com.unidas.apprac.ios.workmanager</string> <string>be.tramckrijter.workmanager.BackgroundTask</string> </array> **Note:** We included multiple identifier formats as recommended by the `workmanager` Flutter plugin documentation: 1. `{bundleId}.ios.workmanager.{taskName}` - Custom task identifier 2. `{bundleId}.ios.workmanager` - Default workmanager identifier 3. `be.tramckrijter.workmanager.BackgroundTask` - Plugin's default identifier (as per plugin documentation) ## AppDelegate.swift Configuration We have configured the `AppDelegate.swift` with the following background processing setup: ```swift // In application(_:didFinishLaunchingWithOptions:) // Configuration to enable background processing via WorkManager // The "processing" mode in UIBackgroundModes allows WorkManager to use BGTaskScheduler (iOS 13+) // This is required to execute scheduled tasks in background (e.g., API calls) // Note: User still needs to have Background App Refresh enabled in iOS settings if UIApplication.shared.backgroundRefreshStatus == .available { // Allows iOS system to schedule background tasks with minimum interval UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum) } ## WorkManager Implementation (Dart/Flutter) ### Initialization ```dart /// Initializes WorkManager static Future<void> initialize() async { await Workmanager().initialize(callbackDispatcher, isInDebugMode: false); print('WorkManagerService: WorkManager initialized'); } ### Task Registration /// Schedules API execution after a specific delay ## Observed Behavior ### Works (Debug/USB Connection) - When running the app via Xcode/USB debugging - Background tasks are scheduled and executed as expected - API calls are made successfully when the app is backgrounded ### Does NOT Work (TestFlight) - When the app is distributed via TestFlight - Background tasks appear to be scheduled (no errors in code) - Tasks are **never executed** when the app is in background - We have tested with: - Background App Refresh enabled in iOS Settings - App used frequently - Device connected to WiFi and charging - Waited for extended periods (hours) ## Possible heart points 1. **Are there any additional configurations required for `BGTaskScheduler` to work in TestFlight/Production builds that are not required for debug builds?** 2. **Is the identifier format correct?** We are using: `br.com.unidas.apprac.ios.workmanager.carrinho_api_task` - Should it match exactly with the task name registered in code? 3. **Are there any known issues with Flutter's `workmanager` plugin and iOS BGTaskScheduler in production environments?** 4. **Is there any way to verify through logs or system diagnostics if the background tasks are being rejected by the system?** 5. **Could there be any conflict between our other background modes (`location`, `remote-notification`) and `processing`?** 6. **Does the Salesforce Marketing Cloud SDK (SFMC) interfere with BGTaskScheduler operations?** ## Additional Context - We have verified that `Background App Refresh` is enabled for our app in iOS Settings - The app has proper entitlements for push notifications and location services - Firebase, SFMC (Salesforce Marketing Cloud), and other SDKs are properly configured - The issue is **only** present in TestFlight builds, not in debug/USB-connected builds ## References - [Apple Documentation - BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler) - [Apple Documentation - Choosing Background Strategies](https://developer.apple.com/documentation/backgroundtasks/choosing_background_strategies_for_your_app) Thank you
2
0
125
Dec ’25
Feature Request: Reason for taskExpiration for BGContinuedProcessingTask
I've tuned my task to be decently resilient, but I found a few issues that caused it to expire regularly. excessive CPU usage -> I'm actually running it behind ReactNative, and I found an issue where I was still updating ReactNative and thus it was keeping it alive the entire time the task was running. Removing this update helped improve stability not updating progress frequently enough ( see https://developer.apple.com/forums/thread/809182?page=1#868247022) My feature request is, would it be possible to get a reason the task was expired in task.expirationHandler? That would be helpful for both the user and for debugging why the task was expired. Thanks!
2
0
246
Dec ’25
Where did I screw up trying concurrency?
I tried making a concurrency-safe data queue. It was going well, until memory check tests crashed. It's part of an unadvertised git project. Its location is: https://github.com/CTMacUser/SynchronizedQueue/commit/84a476e8f719506cbd4cc6ef513313e4e489cae3 It's the blocked-off method "`memorySafetyReferenceTypes'" in "SynchronizedQueueTests.swift." Note that the file and its tests were originally AI slop.
2
0
272
Feb ’26
Trouble creating an XPC service for out-of-process rendering
I'm working on an editor for Bevy games and wanted the following workflow: Launch the game process Host a Metal view for the game's render target Use an XPC service to transfer an MTLSharedTextureHandle Keep the connection for editor/game communication and hot reload As such I created the following editor service: public let XPCEditorServiceName = "org.bevy.editor" public enum XPCEditorMessage: Codable { case ping } public enum XPCEditorReply: Codable { case pong } extension XPCListener { static let bevy = try! XPCListener(service: XPCEditorServiceName) { request in request.accept(XPCEditorService.init) } } struct XPCEditorService: XPCPeerHandler { let session: XPCSession private func handle(_ message: XPCEditorMessage) -> XPCEditorReply? { switch message { case .ping: return .pong } } func handleIncomingRequest(_ message: XPCReceivedMessage) -> (any Encodable)? { do { return handle(try message.decode()) } catch { return nil } } func handleCancellation(error: XPCRichError) { print(error) } } and I initialize it in my app's App initializer: // Launch the XPC service print(XPCListener.bevy) I wanted to test this using an executable target with the following main.swift: let session = try XPCSession(xpcService: XPCEditorServiceName) let response: XPCEditorReply = try session.sendSync(XPCEditorMessage.ping) print("Connected to editor!") The editor prints Listener<org.bevy.editor>(Active) but the game fails with Underlying connection was invalidated. Reason: Connection init failed at lookup with error 3 - No such process What am I doing wrong? PS. Would also appreciate an example of sending & rendering the MTLSharedTextureHandle both in editor & game.
2
0
118
Feb ’26
Migrating away from SMJobBless
I have migrated my code to use SMAppService but am running into trouble deleting the old SMJobBless launchd registration using launchd remove. I am invoking this from a root shell when I detect the daemon and associated plist still exist, then also deleting those files. The remove seems to work (i.e. no errors returned) but launchd list shows the service is registered, with a status code of 28 I am using the same label for SMAppService as previously and suspect this is the reason for the problem. However, I am reluctant to change the label as there will a lot of code changes to do this. If I quit my application, disable the background job in System Settings and run sudo launchd remove in the Terminal then it is removed and my application runs as expected once the background job is re-enabled. Alternatively, a reboot seems to get things going. Any suggestions on to how I could do this more effectively welcome.
2
0
119
Mar ’26
Background upload issue in WatchOS
We are developing a watchOS application that records long audio sessions and uploads them to our backend in chunks (~5 MB each) using pre-signed URLs and URLSession background upload. Current behavior: While audio recording is active, uploads continue successfully even when the app is in the background. Once the recording stops, if multiple chunks (e.g., 10+) are still pending, the remaining uploads do not proceed in the background and appear to be suspended. We attempted to use WKExtendedRuntimeSession (mindfulness type) to allow sufficient time to enqueue background upload tasks, but the session is invalidated when the app goes to the background (e.g., wrist down or app inactive), which prevents reliable scheduling of uploads. Additionally, we added the entitlement: com.apple.developer.extended-runtime-session (mindfulness) in the Watch app entitlements file, but Xcode automatic signing fails with: “Provisioning profile does not include the com.apple.developer.extended-runtime-session entitlement.” It appears that the provisioning profile is not being updated to include this entitlement. Our questions: Is WKExtendedRuntimeSession (mindfulness) expected to support scheduling background URLSession uploads after the app goes to background? How should we reliably complete pending background uploads on watchOS after a long recording session ends? Is there any additional entitlement or recommended approach for this use case? Why is the extended runtime entitlement not being applied to the provisioning profile despite being added in the entitlements file? We are aiming to follow Apple-recommended practices for long-running tasks and background uploads on watchOS. Any guidance would be greatly appreciated.
2
0
141
1w
Called endBackgroundTask but not working
When my app enter to background, I start a background task, and when Expiration happens, I end my background task. The code likes below: backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ if (backgroundTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:backgroundTask]; backgroundTask = UIBackgroundTaskInvalid; [self cancel]; } }); }]; When the breakpoint is triggered at the endBackgroundTask line, I also get the following log: [BackgroundTask] Background task still not ended after expiration handlers were called: <UIBackgroundTaskInfo: 0x282d7ab40>: taskID = 36, taskName = Called by MyApp, from MyMethod, creationTime = 892832 (elapsed = 26). This app will likely be terminated by the system. Call UIApplication.endBackgroundTask(:) to avoid this. The log don't appear every time, so why is that? Is there something wrong with my code?
3
0
3.1k
Jun ’25
Sensorkit - Troubleshooting SRErrorDataInaccessible in Background Fetch with SensorKit
Hello, I am currently developing an iOS application using SensorKit. I encountered an issue when attempting to fetch SensorKit data in the background using background tasks (appRefresh, processing). The following error occurs: In the delegate function func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, failedWithError error: any Error) {}, I receive the error: SRErrorDataInaccessible. In code specific manner: start and handle background fetch (appRefresh) func handleAppRefreshTask(task: BGAppRefreshTask) { logger.logWithServer(level: .default, message: "background fetch start", category: String(describing: BackgroundTaskManager.self)) scheduleBackgroundFetch() let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 let fetchOperation = FetchOperation() queue.addOperation(fetchOperation) task.expirationHandler = { self.logger.logWithServer(level: .error, message: "background fetch expirated", category: String(describing: BackgroundTaskManager.self)) queue.cancelAllOperations() } fetchOperation.completionBlock = { task.setTaskCompleted(success: !fetchOperation.isCancelled) } } Background fetch operation class class FetchOperation: Operation { override func main() { guard !isCancelled else { return } Task { // this function will execute fetch request for all user allowed sensorReader, 'func fetch(_ request: SRFetchRequest)' await SensorkitManager.shared.startFetchAndUpload() } } } I have the following questions: Is it possible to fetch SensorKit data in the background? If it is possible, why does the above error occur? If it is possible, could you provide the solution code and the correct workflow to avoid this error? Thank you.
3
0
1.2k
Feb ’26
Launch daemon running but XPC is down
Hello, I have a question about a edge case scenario. Before that some info on my project- I have a launchdaemon that carries out some business logic, it also has XPC listener (built using C APIs). Question- Can there be a situation when the daemon is up and running but the XPC listener is down(due to some error or crash)? If yes then do I need to handle it in my code or launchd will handle it? when the daemon is stopped or shut down, how do I stop the XPC listener? After getting listener object from xpc_connection_create_mach_service should I just call xpc_connection_cancel followed by a call to xpc_release? Thanks! K
3
0
316
Apr ’25
Memory visibility issue regards to shared data with Dispatch Queue
I’m working with apple dispatch queue in C with the following design: multiple dispatch queues enqueue tasks into a shared context, and a dedicated dispatch queue (let’s call it dispatch queue A) processes these tasks. However, it seems this design has a memory visibility issue. Here’s a simplified version of my setup: I have a shared_context struct that holds: task_lis: a list that stores tasks to be prioritized and run — this list is only modified/processed by dispatch queue A (a serially dispatch queue), so I don't lock around it. cross_thread_tasks: a list that other queues push tasks into, protected by a lock. Other dispatch queues call a function schedule_task that locks and appends a new task to cross_thread_tasks call dispatch_after_f() to schedule a process_task() on dispatch queue A process_task() that processes the task_list and is repeatedly scheduled on dispatch queue A : Swaps cross_thread_tasks into a local list (with locking). Pushes the tasks into task_list. Runs tasks from task_list. Reschedules itself via dispatch_after_f(). Problem: Sometimes the tasks pushed from other threads don’t seem to show up in task_list when process_task() runs. The task_list appears to be missing them, as if the cross-thread tasks aren’t visible. However, if the process_task() is dispatched from the same thread the tasks originate, everything works fine. It seems to be a memory visibility or synchronization issue. Since I only lock around cross_thread_tasks, could it be that changes to task_list (even though modified on dispatch queue A only) are not being properly synchronized or visible across threads? My questions What’s the best practice to ensure shared context is consistently visible across threads when using dispatch queues? Is it mandatory to lock around all tasks? I would love to minimize/avoid lock if possible. Any guidance, debugging tips, or architectural suggestions would be appreciated! =============================== And here is pseudocode of my setup if it helps: struct shared_data { struct linked_list* task_list; } struct shared_context { struct shared_data *data; struct linked_list* cross_thread_tasks; struct thread_mutex* lock; // lock is used to protect cross_thread_tasks } static void s_process_task(void* shared_context){ struct linked_list* local_tasks; // lock and swap the cross_thread_tasks into a local linked list lock(shared_context->lock) swap(shared_context->cross_thread_tasks, local_tasks) unlock(shared_context->lock) // I didnt use lock to protect `shared_context->data` as they are only touched within dispatch queue A in this function. for (task : local_tasks) { linked_list_push(shared_context->data->task_list) } // If the `process_task()` block is dispatched from `schedule_task()` where the task is created, the `shared_context` will be able to access the task properly otherwise not. for (task : shared_context->data->task_list) { run_task_if_timestamp_is_now(task) } timestamp = get_next_timestamp(shared_context->data->task_list) dispatch_after_f(timestamp, dispatch_queueA, shared_context, process_task); } // On dispatch queue B static void schedule_task(struct task* task, void* shared_context) { lock(shared_context->lock) push(shared_context->cross_thread_tasks, task) unlock(shared_context->lock) timestamp = get_timestamp(task) // we only dispatch the task if the timestamp < 1 second. We did this to avoid the dispatch queue schedule the task too far ahead and prevent the shutdown process. Therefore, not all task will be dispatched from the thread it created. if(timestamp < 1 second) dispatch_after_f(timestamp, dispatch_queueA, shared_context, process_task); }
3
0
173
May ’25
XPC codesign requirement crashes application
We have an application that sets a code signing requirement on a XPC connection between a File Provider extension and the main application. Only with a specific Developer ID certificate <DEVELOPER_ID_TEAM_IDENTIFIER> that designated requirement is not accepted and the application crashes with EXC_CRASH (SIGABRT) and the stacktrace Thread 1 Crashed:: Dispatch queue: com.apple.root.default-qos 0 libsystem_kernel.dylib 0x19b556388 __pthread_kill + 8 1 libsystem_pthread.dylib 0x19b58f88c pthread_kill + 296 2 libsystem_c.dylib 0x19b498a3c abort + 124 3 libc++abi.dylib 0x19b545384 abort_message + 132 4 libc++abi.dylib 0x19b533cf4 demangling_terminate_handler() + 344 5 libobjc.A.dylib 0x19b1b8dd4 _objc_terminate() + 156 6 libc++abi.dylib 0x19b544698 std::__terminate(void (*)()) + 16 7 libc++abi.dylib 0x19b547c30 __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88 8 libc++abi.dylib 0x19b547bd8 __cxa_throw + 92 9 libobjc.A.dylib 0x19b1aecf8 objc_exception_throw + 448 10 Foundation 0x19d5c3840 -[NSXPCConnection setCodeSigningRequirement:] + 140 11 libxpcfileprovider.dylib 0x301023048 NSXPCConnection.setCodeSigningRequirementFromTeamIdentifier(_:) + 1796 12 libxpcfileprovider.dylib 0x30101dc94 closure #1 in CallbackFileProviderManager.getFileProviderConnection(_:service:completionHandler:interruptionHandler:exportedObject:) + 1936 13 libxpcfileprovider.dylib 0x30101e110 thunk for @escaping @callee_guaranteed @Sendable (@guaranteed NSXPCConnection?, @guaranteed Error?) -> () + 80 14 Foundation 0x19d46c3a4 __72-[NSFileProviderService getFileProviderConnectionWithCompletionHandler:]_block_invoke_2.687 + 284 15 libdispatch.dylib 0x19b3d7b2c _dispatch_call_block_and_release + 32 16 libdispatch.dylib 0x19b3f185c _dispatch_client_callout + 16 17 libdispatch.dylib 0x19b40e490 + 32 18 libdispatch.dylib 0x19b3e9fa4 _dispatch_root_queue_drain + 736 19 libdispatch.dylib 0x19b3ea5d4 _dispatch_worker_thread2 + 156 20 libsystem_pthread.dylib 0x19b58be28 _pthread_wqthread + 232 21 libsystem_pthread.dylib 0x19b58ab74 start_wqthread + 8 The designated codesign requirement on the XPC connection is set to anchor apple generic and certificate leaf[subject.OU] = <DEVELOPER_ID_TEAM_IDENTIFIER>" We have verified the designated code sign requirement to be valid on both the main bundle and the embedded extension using: codesign --verify -v -R '=anchor apple generic and certificate leaf[subject.OU] = "<DEVELOPER_ID_TEAM_IDENTIFIER>"' *.app codesign --verify -v -R '=anchor apple generic and certificate leaf[subject.OU] = "<DEVELOPER_ID_TEAM_IDENTIFIER>"' *.app/Contents/PlugIns/*
Replies
2
Boosts
0
Views
336
Activity
Sep ’25
Background Task Scheduler
Hello, An application I am working on would like to schedule push notifications for a medication reminder app. I am trying to use BGTaskScheduler to wake up periodically and submit the notifications based on the user's medication schedule. I set up the task registration in my AppDelegate's didFinishLaunchingWithOptions method: BGTaskScheduler.shared.register( forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in self.scheduleNotifications() task.setTaskCompleted(success: true) self.scheduleAppRefresh() } scheduleAppRefresh() I then schedule the task using: func scheduleAppRefresh() { let request = BGAppRefreshTaskRequest(identifier: backgroundTaskIdentifier) request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 1) do { try BGTaskScheduler.shared.submit(request) } catch { } } In my testing, I can see the background task getting called once, but if I do not launch the application during the day. The background task does not get called the next day. Is there something else I need to add to get repeated calls from the BGTaskScheduler? Thank You, JR
Replies
2
Boosts
0
Views
237
Activity
Oct ’25
SSO Extension Fails XPC Connection to System Daemon (mach-lookup exception used)
Hello, I'm running into an issue with a complex macOS application (non-AppStore) structure involving an unsandboxed system daemon and a sandboxed SSO Extension attempting to communicate via XPC Mach service. The macOS app is composed of three main components: Main App: unsandboxed, standard macOS application. System Daemon: unsandboxed executable installed with a .plist to /Library/LaunchDaemons/ and loaded by launchd. It exposes an XPC Mach Service. SSO Extension: a sandboxed Authentication Services Extension (ASAuthorizationProviderExtension). Main App to System Daemon communication works perfectly. The unsandboxed main app can successfully create and use an XPC connection to the System Daemon's Mach service. But SSO Extension cannot establish an XPC connection to the System Daemon's Mach service, despite using the recommended temporary exception entitlement. I have added the following entitlement to the SSO Extension's entitlements file: <key>com.apple.security.temporary-exception.mach-lookup.global-name</key> <array> <string>my.xpc.service.system.daemon</string> </array> (The name my.xpc.service.system.daemon is the exact name registered by the System Daemon in its Launch Daemon plist's MachServices dictionary.) When the SSO Extension attempts to create the connection, the following log output is generated: default 08:11:58.531567-0700 SSOExtension [0x13f19b090] activating connection: mach=true listener=false peer=false name=my.xpc.service.system.daemon default 08:11:58.532150-0700 smd [0xb100d8140] activating connection: mach=false listener=false peer=true name=com.apple.xpc.smd.peer[1575].0xb100d8140 error 08:11:58.532613-0700 smd Item real path failed. Maybe the item has been deleted? error 08:11:58.532711-0700 SSOExtension Unable to find service status () error: 22 The error Unable to find service status () error: 22. Error code 22 typically translates to EINVAL (Invalid argument), but in this context, it seems related to the system's ability to find and activate the service for the sandboxed process. Questions: Is the com.apple.security.temporary-exception.mach-lookup.global-name entitlement sufficient for a sandboxed SSO Extension to look up a system-wide Launch Daemon Mach service, or are there additional restrictions or required entitlements for extensions? The smd log output Item real path failed. Maybe the item has been deleted? seems concerning. Since the unsandboxed main app can connect, this suggests the service is running and registered. Could this error indicate a sandbox permission issue preventing smd from verifying the path for the sandboxed process? Are there specific sandboxing requirements for Mach service names when communicating from an Extension versus a main application? Any guidance on how a sandboxed SSO Extension can reliably connect to an unsandboxed, non-app-group-related system daemon via XPC Mach service would be greatly appreciated!
Replies
2
Boosts
0
Views
242
Activity
Oct ’25
How to view documentation and example codes for Grand Central Dispatch for C
Hi, I am programming in C and would like to use Grand Central Dispatch for parallel computing (I mostly do physics based simulations). I remember there used to be example codes provided by Apple, but can't find those now. Instead I get the plain documentation. May anyone point me to the correct resources? It will be greatly appreciated. Thanks ☺.
Replies
2
Boosts
0
Views
296
Activity
Oct ’25
Bluetooth work with BGTaskScheduler
Hi All, I'm working on an app that needs to connect to BLE device and on defined schedules download data from the device. the amount of data is segnificant and might take around a minute to download. we tought about utilizing both state restoration and preservation for app waking and scheduling (triggered by the ble peripheral) and BGTaskScheduler to schedule a task that will handle a long running task to manage the full data download. now, will this solution in general valid? isnt it a "hack" that goes around the 10s limit that state restoration enforces? i know there are limitations for BGTask (like when it runs, it might be terminated by the system etc) but considering that, can we proceed with this approach without breaching apple guidelines? thank you in advance!
Replies
2
Boosts
0
Views
208
Activity
Oct ’25
BGContinuedProcessingTask UI
When I use BGContinuedProcessingTask to submit a task, my iPhone 12 immediately shows a notification banner displaying the task’s progress. However, on my iPhone 15 Pro Max, there’s no response — the progress UI only appears in the Dynamic Island after I background the app. Why is there a difference in behavior between these two devices? Is it possible to control the UI so that the progress indicator only appears when the app moves to the background?
Replies
2
Boosts
0
Views
311
Activity
Oct ’25
How to safely terminate hanging threads in launched agent context
Hello, In a launched agent, I need to call into a third‑party library that may occasionally hang. At present, these calls are made from a separate thread, but if the thread hangs it cannot be terminated (pthread_cancel/pthread_kill are ineffective). Would Apple recommend isolating this functionality in a separate process that can be force‑terminated if it becomes unresponsive, or is there a preferred approach for handling such cases in launched agents? Can I use the system call fork() in launched agent? Thank you in advance!
Replies
2
Boosts
0
Views
152
Activity
Oct ’25
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?
Replies
2
Boosts
0
Views
362
Activity
Jan ’26
NotificationCenter.notifications(named:) appears to buffer internally and can drop notifications, but is this documented anywhere?
I've experimentally seen that the notifications(named:) API of NotificationCenter appears to buffer observed notifications internally. In local testing it appears to be limited to 8 messages. I've been unable to find any documentation of this fact, and the behavior seems like it could lead to software bugs if code is not expecting notifications to potentially be dropped. Is this behavior expected and documented somewhere? Here is a sample program demonstrating the behavioral difference between the Combine and AsyncSequence-based notification observations: @Test nonisolated func testNotificationRace() async throws { let testName = Notification.Name("TestNotification") let notificationCount = 100 var observedAsyncIDs = [Int]() var observedCombineIDs = [Int]() let subscribe = Task { @MainActor in print("setting up observer...") let token = NotificationCenter.default.publisher(for: testName) .sink { value in let id = value.userInfo?["id"] as! Int observedCombineIDs.append(id) print("🚜 observed note with id: \(id)") } defer { extendLifetime(token) } for await note in NotificationCenter.default.notifications(named: testName) { let id: Int = note.userInfo?["id"] as! Int print("🚰 observed note with id: \(id)") observedAsyncIDs.append(id) if id == notificationCount { break } } } let post = Task { @MainActor in for i in 1...notificationCount { NotificationCenter.default.post( name: testName, object: nil, userInfo: ["id": i] ) } } _ = await (post.value, subscribe.value) #expect(observedAsyncIDs.count == notificationCount) // 🛑 Expectation failed: (observedAsyncIDs.count → 8) == (notificationCount → 100) #expect(observedCombineIDs == Array(1...notificationCount)) print("done") }
Replies
2
Boosts
0
Views
292
Activity
Dec ’25
Flutter library that basically makes a call every "x" minutes if the app is in the background.
Hi everyone, could you help us? We implemented a Flutter library that basically makes a call every x minutes if the app is in the background, but when I generate the version via TestFlight for testing, it doesn't work. Can you help us understand why? Below is a more detailed technical description. Apple Developer Technical Support Request Subject: BGTaskScheduler / Background Tasks Not Executing in TestFlight - Flutter App with workmanager Plugin Issue Summary Background tasks scheduled using BGTaskScheduler are not executing when the app is distributed via TestFlight. The same implementation works correctly when running the app locally via USB/Xcode debugging. We are developing a Flutter application that needs to perform periodic API calls when the app is in the background. We have followed all documentation and implemented the required configurations, but background tasks are not being executed in the TestFlight build. App Information Field Value App Version 3.1.15 (Build 311) iOS Minimum Deployment Target iOS 15.0 Framework Flutter Flutter SDK Version ^3.7.2 Technical Environment Flutter Dependencies (Background Task Related) Package Version Purpose workmanager ^0.9.0+3 Main background task scheduler (uses BGTaskScheduler on iOS 13+) flutter_background_service ^5.0.5 Background service management flutter_background_service_android ^6.2.4 Android-specific background service flutter_local_notifications ^19.4.2 Local notifications for background alerts timezone ^0.10.0 Timezone support for scheduling Other Relevant Flutter Dependencies Package Version firebase_core 4.0.0 firebase_messaging (via native Podfile) sfmc (Salesforce Marketing Cloud) ^9.0.0 geolocator ^14.0.0 permission_handler ^12.0.0+1 Info.plist Configuration We have added the following configurations to Info.plist: UIBackgroundModes <key>UIBackgroundModes</key> <array> <string>location</string> <string>remote-notification</string> <string>processing</string> </array> ### BGTaskSchedulerPermittedIdentifiers ```xml <key>BGTaskSchedulerPermittedIdentifiers</key> <array> <string>br.com.unidas.apprac.ios.workmanager.carrinho_api_task</string> <string>br.com.unidas.apprac.ios.workmanager</string> <string>be.tramckrijter.workmanager.BackgroundTask</string> </array> **Note:** We included multiple identifier formats as recommended by the `workmanager` Flutter plugin documentation: 1. `{bundleId}.ios.workmanager.{taskName}` - Custom task identifier 2. `{bundleId}.ios.workmanager` - Default workmanager identifier 3. `be.tramckrijter.workmanager.BackgroundTask` - Plugin's default identifier (as per plugin documentation) ## AppDelegate.swift Configuration We have configured the `AppDelegate.swift` with the following background processing setup: ```swift // In application(_:didFinishLaunchingWithOptions:) // Configuration to enable background processing via WorkManager // The "processing" mode in UIBackgroundModes allows WorkManager to use BGTaskScheduler (iOS 13+) // This is required to execute scheduled tasks in background (e.g., API calls) // Note: User still needs to have Background App Refresh enabled in iOS settings if UIApplication.shared.backgroundRefreshStatus == .available { // Allows iOS system to schedule background tasks with minimum interval UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum) } ## WorkManager Implementation (Dart/Flutter) ### Initialization ```dart /// Initializes WorkManager static Future<void> initialize() async { await Workmanager().initialize(callbackDispatcher, isInDebugMode: false); print('WorkManagerService: WorkManager initialized'); } ### Task Registration /// Schedules API execution after a specific delay ## Observed Behavior ### Works (Debug/USB Connection) - When running the app via Xcode/USB debugging - Background tasks are scheduled and executed as expected - API calls are made successfully when the app is backgrounded ### Does NOT Work (TestFlight) - When the app is distributed via TestFlight - Background tasks appear to be scheduled (no errors in code) - Tasks are **never executed** when the app is in background - We have tested with: - Background App Refresh enabled in iOS Settings - App used frequently - Device connected to WiFi and charging - Waited for extended periods (hours) ## Possible heart points 1. **Are there any additional configurations required for `BGTaskScheduler` to work in TestFlight/Production builds that are not required for debug builds?** 2. **Is the identifier format correct?** We are using: `br.com.unidas.apprac.ios.workmanager.carrinho_api_task` - Should it match exactly with the task name registered in code? 3. **Are there any known issues with Flutter's `workmanager` plugin and iOS BGTaskScheduler in production environments?** 4. **Is there any way to verify through logs or system diagnostics if the background tasks are being rejected by the system?** 5. **Could there be any conflict between our other background modes (`location`, `remote-notification`) and `processing`?** 6. **Does the Salesforce Marketing Cloud SDK (SFMC) interfere with BGTaskScheduler operations?** ## Additional Context - We have verified that `Background App Refresh` is enabled for our app in iOS Settings - The app has proper entitlements for push notifications and location services - Firebase, SFMC (Salesforce Marketing Cloud), and other SDKs are properly configured - The issue is **only** present in TestFlight builds, not in debug/USB-connected builds ## References - [Apple Documentation - BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler) - [Apple Documentation - Choosing Background Strategies](https://developer.apple.com/documentation/backgroundtasks/choosing_background_strategies_for_your_app) Thank you
Replies
2
Boosts
0
Views
125
Activity
Dec ’25
Feature Request: Reason for taskExpiration for BGContinuedProcessingTask
I've tuned my task to be decently resilient, but I found a few issues that caused it to expire regularly. excessive CPU usage -> I'm actually running it behind ReactNative, and I found an issue where I was still updating ReactNative and thus it was keeping it alive the entire time the task was running. Removing this update helped improve stability not updating progress frequently enough ( see https://developer.apple.com/forums/thread/809182?page=1#868247022) My feature request is, would it be possible to get a reason the task was expired in task.expirationHandler? That would be helpful for both the user and for debugging why the task was expired. Thanks!
Replies
2
Boosts
0
Views
246
Activity
Dec ’25
Where did I screw up trying concurrency?
I tried making a concurrency-safe data queue. It was going well, until memory check tests crashed. It's part of an unadvertised git project. Its location is: https://github.com/CTMacUser/SynchronizedQueue/commit/84a476e8f719506cbd4cc6ef513313e4e489cae3 It's the blocked-off method "`memorySafetyReferenceTypes'" in "SynchronizedQueueTests.swift." Note that the file and its tests were originally AI slop.
Replies
2
Boosts
0
Views
272
Activity
Feb ’26
Trouble creating an XPC service for out-of-process rendering
I'm working on an editor for Bevy games and wanted the following workflow: Launch the game process Host a Metal view for the game's render target Use an XPC service to transfer an MTLSharedTextureHandle Keep the connection for editor/game communication and hot reload As such I created the following editor service: public let XPCEditorServiceName = "org.bevy.editor" public enum XPCEditorMessage: Codable { case ping } public enum XPCEditorReply: Codable { case pong } extension XPCListener { static let bevy = try! XPCListener(service: XPCEditorServiceName) { request in request.accept(XPCEditorService.init) } } struct XPCEditorService: XPCPeerHandler { let session: XPCSession private func handle(_ message: XPCEditorMessage) -> XPCEditorReply? { switch message { case .ping: return .pong } } func handleIncomingRequest(_ message: XPCReceivedMessage) -> (any Encodable)? { do { return handle(try message.decode()) } catch { return nil } } func handleCancellation(error: XPCRichError) { print(error) } } and I initialize it in my app's App initializer: // Launch the XPC service print(XPCListener.bevy) I wanted to test this using an executable target with the following main.swift: let session = try XPCSession(xpcService: XPCEditorServiceName) let response: XPCEditorReply = try session.sendSync(XPCEditorMessage.ping) print("Connected to editor!") The editor prints Listener<org.bevy.editor>(Active) but the game fails with Underlying connection was invalidated. Reason: Connection init failed at lookup with error 3 - No such process What am I doing wrong? PS. Would also appreciate an example of sending & rendering the MTLSharedTextureHandle both in editor & game.
Replies
2
Boosts
0
Views
118
Activity
Feb ’26
Migrating away from SMJobBless
I have migrated my code to use SMAppService but am running into trouble deleting the old SMJobBless launchd registration using launchd remove. I am invoking this from a root shell when I detect the daemon and associated plist still exist, then also deleting those files. The remove seems to work (i.e. no errors returned) but launchd list shows the service is registered, with a status code of 28 I am using the same label for SMAppService as previously and suspect this is the reason for the problem. However, I am reluctant to change the label as there will a lot of code changes to do this. If I quit my application, disable the background job in System Settings and run sudo launchd remove in the Terminal then it is removed and my application runs as expected once the background job is re-enabled. Alternatively, a reboot seems to get things going. Any suggestions on to how I could do this more effectively welcome.
Replies
2
Boosts
0
Views
119
Activity
Mar ’26
Background upload issue in WatchOS
We are developing a watchOS application that records long audio sessions and uploads them to our backend in chunks (~5 MB each) using pre-signed URLs and URLSession background upload. Current behavior: While audio recording is active, uploads continue successfully even when the app is in the background. Once the recording stops, if multiple chunks (e.g., 10+) are still pending, the remaining uploads do not proceed in the background and appear to be suspended. We attempted to use WKExtendedRuntimeSession (mindfulness type) to allow sufficient time to enqueue background upload tasks, but the session is invalidated when the app goes to the background (e.g., wrist down or app inactive), which prevents reliable scheduling of uploads. Additionally, we added the entitlement: com.apple.developer.extended-runtime-session (mindfulness) in the Watch app entitlements file, but Xcode automatic signing fails with: “Provisioning profile does not include the com.apple.developer.extended-runtime-session entitlement.” It appears that the provisioning profile is not being updated to include this entitlement. Our questions: Is WKExtendedRuntimeSession (mindfulness) expected to support scheduling background URLSession uploads after the app goes to background? How should we reliably complete pending background uploads on watchOS after a long recording session ends? Is there any additional entitlement or recommended approach for this use case? Why is the extended runtime entitlement not being applied to the provisioning profile despite being added in the entitlements file? We are aiming to follow Apple-recommended practices for long-running tasks and background uploads on watchOS. Any guidance would be greatly appreciated.
Replies
2
Boosts
0
Views
141
Activity
1w
Called endBackgroundTask but not working
When my app enter to background, I start a background task, and when Expiration happens, I end my background task. The code likes below: backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ if (backgroundTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:backgroundTask]; backgroundTask = UIBackgroundTaskInvalid; [self cancel]; } }); }]; When the breakpoint is triggered at the endBackgroundTask line, I also get the following log: [BackgroundTask] Background task still not ended after expiration handlers were called: <UIBackgroundTaskInfo: 0x282d7ab40>: taskID = 36, taskName = Called by MyApp, from MyMethod, creationTime = 892832 (elapsed = 26). This app will likely be terminated by the system. Call UIApplication.endBackgroundTask(:) to avoid this. The log don't appear every time, so why is that? Is there something wrong with my code?
Replies
3
Boosts
0
Views
3.1k
Activity
Jun ’25
Sensorkit - Troubleshooting SRErrorDataInaccessible in Background Fetch with SensorKit
Hello, I am currently developing an iOS application using SensorKit. I encountered an issue when attempting to fetch SensorKit data in the background using background tasks (appRefresh, processing). The following error occurs: In the delegate function func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, failedWithError error: any Error) {}, I receive the error: SRErrorDataInaccessible. In code specific manner: start and handle background fetch (appRefresh) func handleAppRefreshTask(task: BGAppRefreshTask) { logger.logWithServer(level: .default, message: "background fetch start", category: String(describing: BackgroundTaskManager.self)) scheduleBackgroundFetch() let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 let fetchOperation = FetchOperation() queue.addOperation(fetchOperation) task.expirationHandler = { self.logger.logWithServer(level: .error, message: "background fetch expirated", category: String(describing: BackgroundTaskManager.self)) queue.cancelAllOperations() } fetchOperation.completionBlock = { task.setTaskCompleted(success: !fetchOperation.isCancelled) } } Background fetch operation class class FetchOperation: Operation { override func main() { guard !isCancelled else { return } Task { // this function will execute fetch request for all user allowed sensorReader, 'func fetch(_ request: SRFetchRequest)' await SensorkitManager.shared.startFetchAndUpload() } } } I have the following questions: Is it possible to fetch SensorKit data in the background? If it is possible, why does the above error occur? If it is possible, could you provide the solution code and the correct workflow to avoid this error? Thank you.
Replies
3
Boosts
0
Views
1.2k
Activity
Feb ’26
Background terminations increase
We've seen a recent increase in background terminations: blue - System Pressure orange - Task Timeout I'm trying to understand the increase in system-pressure terminations, since there's no corresponding increase in memory at suspension. Are there other system resources for which iOS will terminate an app?
Replies
3
Boosts
0
Views
279
Activity
Jun ’25
Launch daemon running but XPC is down
Hello, I have a question about a edge case scenario. Before that some info on my project- I have a launchdaemon that carries out some business logic, it also has XPC listener (built using C APIs). Question- Can there be a situation when the daemon is up and running but the XPC listener is down(due to some error or crash)? If yes then do I need to handle it in my code or launchd will handle it? when the daemon is stopped or shut down, how do I stop the XPC listener? After getting listener object from xpc_connection_create_mach_service should I just call xpc_connection_cancel followed by a call to xpc_release? Thanks! K
Replies
3
Boosts
0
Views
316
Activity
Apr ’25
Memory visibility issue regards to shared data with Dispatch Queue
I’m working with apple dispatch queue in C with the following design: multiple dispatch queues enqueue tasks into a shared context, and a dedicated dispatch queue (let’s call it dispatch queue A) processes these tasks. However, it seems this design has a memory visibility issue. Here’s a simplified version of my setup: I have a shared_context struct that holds: task_lis: a list that stores tasks to be prioritized and run — this list is only modified/processed by dispatch queue A (a serially dispatch queue), so I don't lock around it. cross_thread_tasks: a list that other queues push tasks into, protected by a lock. Other dispatch queues call a function schedule_task that locks and appends a new task to cross_thread_tasks call dispatch_after_f() to schedule a process_task() on dispatch queue A process_task() that processes the task_list and is repeatedly scheduled on dispatch queue A : Swaps cross_thread_tasks into a local list (with locking). Pushes the tasks into task_list. Runs tasks from task_list. Reschedules itself via dispatch_after_f(). Problem: Sometimes the tasks pushed from other threads don’t seem to show up in task_list when process_task() runs. The task_list appears to be missing them, as if the cross-thread tasks aren’t visible. However, if the process_task() is dispatched from the same thread the tasks originate, everything works fine. It seems to be a memory visibility or synchronization issue. Since I only lock around cross_thread_tasks, could it be that changes to task_list (even though modified on dispatch queue A only) are not being properly synchronized or visible across threads? My questions What’s the best practice to ensure shared context is consistently visible across threads when using dispatch queues? Is it mandatory to lock around all tasks? I would love to minimize/avoid lock if possible. Any guidance, debugging tips, or architectural suggestions would be appreciated! =============================== And here is pseudocode of my setup if it helps: struct shared_data { struct linked_list* task_list; } struct shared_context { struct shared_data *data; struct linked_list* cross_thread_tasks; struct thread_mutex* lock; // lock is used to protect cross_thread_tasks } static void s_process_task(void* shared_context){ struct linked_list* local_tasks; // lock and swap the cross_thread_tasks into a local linked list lock(shared_context->lock) swap(shared_context->cross_thread_tasks, local_tasks) unlock(shared_context->lock) // I didnt use lock to protect `shared_context->data` as they are only touched within dispatch queue A in this function. for (task : local_tasks) { linked_list_push(shared_context->data->task_list) } // If the `process_task()` block is dispatched from `schedule_task()` where the task is created, the `shared_context` will be able to access the task properly otherwise not. for (task : shared_context->data->task_list) { run_task_if_timestamp_is_now(task) } timestamp = get_next_timestamp(shared_context->data->task_list) dispatch_after_f(timestamp, dispatch_queueA, shared_context, process_task); } // On dispatch queue B static void schedule_task(struct task* task, void* shared_context) { lock(shared_context->lock) push(shared_context->cross_thread_tasks, task) unlock(shared_context->lock) timestamp = get_timestamp(task) // we only dispatch the task if the timestamp < 1 second. We did this to avoid the dispatch queue schedule the task too far ahead and prevent the shutdown process. Therefore, not all task will be dispatched from the thread it created. if(timestamp < 1 second) dispatch_after_f(timestamp, dispatch_queueA, shared_context, process_task); }
Replies
3
Boosts
0
Views
173
Activity
May ’25