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

How to force cancel a task that doesn't need cleanup and doesn't check for cancellation?
How can you force cancel a task that doesn't need cleanup and doesn't check for cancellation? If this cannot be done, would this be a useful addition to Swift? Here is the situation: The async method doesn't check for cancellation since it is not doing anything repetively (for example in a loop). For example, the method may be doing "try JSONDecoder().decode(Dictionary<String, ...>.self, from: data)" where data is a large amount. The method doesn't need cleanup. I would like the force cancellation to throw an error. I am already handling errors for the async method. My intended situation if that the user request the async method to get some JSON encoded data, but since it is taking longer that they are willing to wait, they would tap a cancellation button that the app provides.
1
0
94
May ’25
What happens after BGContinuedProcessingTask "expires"?
If I create a BGContinuedProcessingTaskRequest, register it, and then "do work" within it appropriately reporting progress, and before my task has finished doing all the work it had to do, its expirationHandler triggers... does the task later try again? Or does it lose the execution opportunity until the app is next re-launched to the foreground? In my testing, I never saw my task execute again once expired (which suggests the latter?). I was able to easily force this expiry by starting my task, backgrounding my app, then launching the iOS Camera App. My example is just using test code inspired from https://developer.apple.com/documentation/backgroundtasks/performing-long-running-tasks-on-ios-and-ipados let request = BGContinuedProcessingTaskRequest(identifier: taskIdentifier, title: "Video Upload", subtitle: "Starting Upload") request.strategy = .queue BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { task in guard let task = task as? BGContinuedProcessingTask else { return } print("i am a good task") var wasExpired = false task.expirationHandler = { wasExpired = true } let progress = task.progress progress.totalUnitCount = 100 while !progress.isFinished && !wasExpired { progress.completedUnitCount += 1 let formattedProgress = String(format: "%.2f", progress.fractionCompleted * 100) task.updateTitle(task.title, subtitle: "Completed \(formattedProgress)%") sleep(1) } if progress.isFinished { print ("i was a good task") task.setTaskCompleted(success: true) } else { print("i was not a good task") task.setTaskCompleted(success: false) } } try? BGTaskScheduler.shared.submit(request) Apologies if this is clearly stated somewhere and I'm missing it.
1
0
70
Nov ’25
Effect of app nap of Timer
I'm developing a macOS application that tracks the duration of a user's session using a timer, which is displayed both in the main window and in an menu bar extra view. I have a couple of questions regarding the timer's behavior: What happens to the timer if the user closes the application's window (causing the app to become inactive) but does not fully quit it? Does the timer continue to run, pause, or behave in some other way? Will the app nap feature stop the timer when app is in-active state? When the application is inactive and the system is either in sleep mode or locked, does the timer’s tolerance get affected? In other words, will the timer fire with any additional delay compared to its scheduled time under these conditions?
1
0
76
Mar ’25
BGContinuedProcessingTask Notification Error
Hello im creating an expo module using this new API, but the problem i found currently testing this functionality is that when the task fails, the notification error doesn't go away and is always showing the failed task notification even if i start a new task and complete that one. I want to implement this module into the production app but i feel like having always the notification error might confuse our users or find it a bit bothersome. Is there a way for the users to remove this notification? Best regards!
1
0
91
Sep ’25
XPC - performance/load testing
I have an XPC server running on macOS and want to perform comprehensive performance and load testing to evaluate its efficiency, responsiveness, and scalability. Specifically, I need to measure factors such as request latency, throughput, and how well it handles concurrent connections under different load conditions. What are the best tools, frameworks, or methodologies for testing an XPC service? Additionally, are there any best practices for simulating real-world usage scenarios and identifying potential bottlenecks?
1
1
129
Apr ’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
111
Oct ’25
ExtensionKit & ExtensionFoundation process lifecycle
An XPC service’s process has a system-managed lifecycle: the process is launched on-demand when another process tries to connect to it, and the system can decide to kill it when system resources are low. XPC services can tell the system when they shouldn’t be killed using xpc_transaction_begin/end. Do extensions created with ExtensionFoundation and/or ExtensionKit have the same behavior?
1
0
166
Jul ’25
Some questions about how to use the Background Assets capability on iOS
Regarding the Background Assets capability on iOS: In the install scenario, resources defined as the "install" type are incorporated into the App Store download progress. Do resources of the "update" type in the update scenario also get incorporated into the App Store download progress in the same way? If an exception occurs during the download of install-type resources and the download cannot proceed further, will the system no longer actively block users from launching the app and instead enable the launch button? Currently, if a user has enabled automatic updates on their device, after the app is updated and released on the App Store, will the Background Assets download start immediately once the automatic update completes? Or does Background Assets have its own built-in scheduling logic that prevents it from running concurrently with the automatic update?
1
0
54
1w
How to prevent the main app from being terminated by the system during long - term system - level recording
After logging in to the main App, turn on screen recording, then switch to the interface of another App to perform operations. After about ten-odd minutes, when returning to the main App, it was found that the app was forcefully quit by the system, and subsequent operations could not be carried out.
1
0
108
May ’25
Operation not permitted on xpc_listener_create
Hi, I'm trying to create a launch daemon that uses XPC to receive requests from an unprivileged app. Ultimately both components will be written in Go. For now I'm trying to write a PoC in Objective-C to make sure I get everything right, so I'm compiling / signing from the CLI, and writing plist files by hand -- I'm not using XCode. My current daemon code is pretty much the same as the boilerplate code that XCode generates when creating a new 'XPC Service': #import <stdio.h> #include <xpc/xpc.h> int main(int argc, char *argv[]) { xpc_rich_error_t error; dispatch_queue_t queue = dispatch_queue_create("com.foobar.daemon", DISPATCH_QUEUE_SERIAL); xpc_listener_t listener = xpc_listener_create( "com.foobar.daemon", queue, XPC_LISTENER_CREATE_NONE, ^(xpc_session_t _Nonnull peer) { xpc_session_set_incoming_message_handler(peer, ^(xpc_object_t _Nonnull message) { int64_t firstNumber = xpc_dictionary_get_int64(message, "firstNumber"); int64_t secondNumber = xpc_dictionary_get_int64(message, "secondNumber"); // Create a reply and send it back to the client. xpc_object_t reply = xpc_dictionary_create_reply(message); xpc_dictionary_set_int64(reply, "result", firstNumber + secondNumber); xpc_rich_error_t replyError = xpc_session_send_message(peer, reply); if (replyError) { printf("Reply failed, error: %s", xpc_rich_error_copy_description(replyError)); } }); }, &error); if (error != NULL) { printf("ERROR: %s\n", xpc_rich_error_copy_description(error)); exit(1); } printf("Created listener: %s", xpc_listener_copy_description(listener)); // Resuming the serviceListener starts this service. This method does not return. dispatch_main(); return 0; } I'm compiling, signing and installing my daemon with the following commands: build_foobar() { clang -Wall -x objective-c -o com.foobar.daemon poc/main.m codesign --force --verify --verbose --options=runtime \ --identifier="com.foobar.daemon" \ --sign="Mac Developer: Albin Kerouanton (XYZ)" \ --entitlements=poc/entitlements.plist \ com.foobar.daemon } install_foobar() { sudo cp com.foobar.daemon /Library/PrivilegedHelperTools/com.foobar.daemon sudo cp poc/com.foobar.daemon.plist /Library/LaunchDaemons/com.foobar.daemon.plist sudo launchctl bootout system/com.foobar.daemon || true sudo launchctl bootstrap system /Library/LaunchDaemons/com.foobar.daemon.plist } Here's the content of my entitlements.plist file: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.application-identifier</key> <string>ABCD.com.foobar.daemon</string> </dict> </plist> And finally, here's my launchd plist file: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.foobar.daemon</string> <key>Program</key> <string>/Library/PrivilegedHelperTools/com.foobar.daemon</string> <key>ProgramArguments</key> <array> <string>/Library/PrivilegedHelperTools/com.foobar.daemon</string> </array> <key>RunAtLoad</key> <false/> <key>StandardOutPath</key> <string>/tmp/com.foobar.daemon.out.log</string> <key>StandardErrorPath</key> <string>/tmp/com.foobar.daemon.err.log</string> <key>Debug</key> <true/> </dict> </plist> Whenever I start my service using sudo launchctl start com.foobar.daemon, it exits with the following error message: ERROR: Unable to activate listener: failed at listener activation with error 1 - Operation not permitted System logs don't show anything interesting -- they're just repeating the same error message. I tried to add / remove some properties from both the entitlement and the launchd plist file but to no avail. Any idea what's going wrong?
1
0
575
Jan ’25
Background Download Not Working in release builds- flutter_downloader
Issue: Background downloads using the flutter_downloader package work perfectly in debug mode and release mode when run directly from Xcode (plugged in). However, when I create an archive build and install the app separately (via TestFlight or direct IPA install), the background download stops working as soon as the app is minimized. ✅ What I’ve already done Info.plist <key>UIBackgroundModes</key> <array> <string>remote-notification</string> <string>fetch</string> <string>processing</string> <string>audio</string> <string>push-to-talk</string> </array> AppDelegate.swift import UIKit import Flutter import Firebase import flutter_downloader import BackgroundTasks @main @objc class AppDelegate: FlutterAppDelegate { static let backgroundChannel = "com.example.app/background_service" private var backgroundCompletionHandler: (() -> Void)? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() GeneratedPluginRegistrant.register(with: self) FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins) if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self } if #available(iOS 13.0, *) { registerBackgroundTask() } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } @available(iOS 13.0, *) private func registerBackgroundTask() { BGTaskScheduler.shared.register( forTaskWithIdentifier: "com.example.app.process_download_queue", using: nil ) { [weak self] task in guard let self = self else { return } self.handleDownloadQueueTask(task: task as! BGProcessingTask) } } @available(iOS 13.0, *) private func handleDownloadQueueTask(task: BGProcessingTask) { scheduleNextDownloadTask() let headlessEngine = FlutterEngine(name: "BackgroundTaskEngine", project: nil, allowHeadlessExecution: true) headlessEngine.run() let channel = FlutterMethodChannel( name: AppDelegate.backgroundChannel, binaryMessenger: headlessEngine.binaryMessenger ) task.expirationHandler = { channel.invokeMethod("backgroundTaskExpired", arguments: nil) } channel.invokeMethod("processNextInBackground", arguments: nil) { result in task.setTaskCompleted(success: (result as? Bool) ?? false) } } override func application( _ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void ) { self.backgroundCompletionHandler = completionHandler super.application(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler) } override func applicationDidEnterBackground(_ application: UIApplication) { if #available(iOS 13.0, *) { scheduleNextDownloadTask() } } @available(iOS 10.0, *) override func userNotificationCenter( _ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void ) { if #available(iOS 14.0, *) { completionHandler([.list, .banner, .badge, .sound]) } else { completionHandler([.alert, .badge, .sound]) } } @available(iOS 10.0, *) override func userNotificationCenter( _ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void ) { completionHandler() } } // MARK: - Helper @available(iOS 13.0, *) func scheduleNextDownloadTask() { let request = BGProcessingTaskRequest(identifier: "com.example.app.process_download_queue") request.requiresNetworkConnectivity = true request.requiresExternalPower = false request.earliestBeginDate = Date(timeIntervalSinceNow: 60) do { try BGTaskScheduler.shared.submit(request) print("BGTask: Download queue processing task scheduled successfully.") } catch { print("BGTask: Could not schedule download queue task: \(error)") } } private func registerPlugins(registry: FlutterPluginRegistry) { if !registry.hasPlugin("FlutterDownloaderPlugin") { FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!) } } 🧩 Observations Background download works correctly when: The app is plugged in and run via Xcode (release/debug) It stops working when: The app is installed from an archived build (IPA/TestFlight) and minimized All entitlements and background modes are properly added. Provisioning profile includes required background modes. ❓Question Is there any known limitation or signing difference between Xcode run and archived release builds that could cause URLSession background tasks not to trigger? Has anyone faced a similar issue when using flutter_downloader on iOS 13+ with BGTaskScheduler or URLSession background configuration? Any help or working setup example for production/TestFlight would be appreciated.
1
0
69
Nov ’25
SMAppService daemon not running
My app uses SMAppService to register a privileged helper, the helper registers without errors, and can be seen in System Settings. I can get a connection to the service and a remote object proxy, but the helper process cannot be found in Activity Monitor and the calls to the proxy functions seem to always fail without showing any specific errors. What could be causing this situation?
1
0
240
Jul ’25
Mac: Best way to distinguish native app process and script process spawned from executable (e.g. python node) through process_id
I'm working on a Mac app that receives a process ID via NSXPCConnection, and I'm trying to figure out the best way to determine whether that process is a native macOS app like Safari—with bundles and all—or just a script launched by something like Node or Python. The executable is signed with a Team ID using codesign. I was thinking about getting the executable's path as one way to handle it, but I’m wondering if there’s a more reliable method than relying on the folder structure.
1
0
203
Sep ’25
Prevent my app from background activity
When I search, it's always people trying to do stuff in the background. I want my app to only do stuff when it is active. And this post https://developer.apple.com/forums/thread/685525 seems to have prevented replies from the start. Which means it's just a documentation page and does not belong in the discussion forums at all, because it prevents all discussion.
1
0
88
May ’25
System Network Extension XPC with LaunchAgent
I've discovered that a system network extension can communicate with a LaunchDaemon (loaded using SMAppService) over XPC, provided that the XPC service name begins with the team ID. If I move the launchd daemon plist to Contents/Library/LaunchAgents and swap the SMAppService.daemon calls to SMAppService.agent calls, and remove the .privileged option to NSXPCConnection, the system extension receives "Couldn't communicate with a helper application" as an error when trying to reach the LaunchAgent advertised service. Is this limitation by design? I imagine it is, but wanted to check before I spent any more time on it.
1
0
213
Jul ’25
Background refresh or processing app
I am writing an app which mainly is used to update data used by other apps on the device. After the user initializes some values in the app, they almost never have to return to it (occasionally to add a "friend"). The app needs to run a background task at least daily, however, without the user's intervention (or even awareness, once they've given permission). My understanding of background refresh tasks is that if the user doesn't activate the app in the foreground periodically, the scheduled background tasks may never run. If this is true, do I want to use a background processing task instead, or is there a better solution (or have I misunderstood entirely)?
1
0
397
Jan ’25