XPC is a a low-level (libSystem) interprocess communication mechanism that is based on serialized property lists.

XPC Documentation

Pinned Posts

Posts under XPC tag

46 Posts
Sort by:
Post not yet marked as solved
1 Replies
93 Views
I am attempting to install and utilize an agent using the new(ish) SMAppService API with an existing app. The agent appears to install (no error is returned), but when I try to start the agent from Terminal, I get the following in the launchd.log: 2024-04-22 09:57:27.469039 (gui/502/com.redacted.service.agent) : internal event: WILL_SPAWN, code = 0 2024-04-22 09:57:27.469080 (gui/502/com.redacted.service.agent) : service state: spawn scheduled 2024-04-22 09:57:27.469081 (gui/502/com.redacted.service.agent) : service state: spawning 2024-04-22 09:57:27.469100 (gui/502/com.redacted.service.agent) : launching: one-shot 2024-04-22 09:57:27.469105 (gui/502/com.redacted.service.agent) : Allowing non-reentrant proxy for resolving path 2024-04-22 09:57:27.469947 (gui/502/com.redacted.service.agent [71866]) : xpcproxy spawned with pid 71866 2024-04-22 09:57:27.469960 (gui/502/com.redacted.service.agent [71866]) : internal event: SPAWNED, code = 0 2024-04-22 09:57:27.469964 (gui/502/com.redacted.service.agent [71866]) : service state: xpcproxy 2024-04-22 09:57:27.469997 (gui/502/com.redacted.service.agent [71866]) : internal event: SOURCE_ATTACH, code = 0 2024-04-22 09:57:27.506283 (gui/502/com.redacted.service.agent [71866]) : Service could not initialize: posix_spawn(/Users/chrisf/Library/Developer/Xcode/DerivedData/Redacted-gttupgdyakodzddurpavhmscwabs/Build/Products/Debug/Redacted App.app/Contents/MacOS/Service Agent.app), error 0xd - Permission denied 2024-04-22 09:57:27.506306 (gui/502/com.redacted.service.agent [71866]) : initialization failure: 23E224: xpcproxy + 31420 [1098][A7EF179C-FBCC-349E-A7D2-09B2F1408413]: 0xd 2024-04-22 09:57:27.506309 (gui/502/com.redacted.service.agent [71866]) : internal event: INIT, code = 13 2024-04-22 09:57:27.506313 (gui/502/com.redacted.service.agent [71866]) : job state = spawn failed 2024-04-22 09:57:27.507148 (gui/502/com.redacted.service.agent [71866]) : xpcproxy exited due to exit(78) 2024-04-22 09:57:27.507153 (gui/502/com.redacted.service.agent [71866]) : exited due to exit(78) 2024-04-22 09:57:27.507162 (gui/502/com.redacted.service.agent [71866]) : already handled failed init, ignoring 2024-04-22 09:57:27.507170 (gui/502/com.redacted.service.agent [71866]) : service state: exited 2024-04-22 09:57:27.507186 (gui/502/com.redacted.service.agent [71866]) : internal event: EXITED, code = 0 (tldr: error 0xd - Permission denied) I'd also be curious how we are expected to launch agents once registered with SMAppService. Is it sufficient simply to make an XPC call to an exposed method? Thanks!
Posted
by
Post marked as solved
2 Replies
143 Views
I noticed a problem while writing a program using XPC on macOS. When I write it in the form of a closure that receives the result of an XPC call, I can't receive it forever. I add an XPC target in Xcode, the sample code is used in the pass closure format, but can't I use closure passing with XPC? My Environment: Xcode 15.3 macOS 14.4.1 caller (closure version) struct ContentView: View { @State var callbackResult: String = "Waiting…" var body: some View { Form { Section("Run XPC Call with no argument and no return value using callback") { Button("Run…") { callbackResult = "Running…" let service = NSXPCConnection(serviceName: "net.mtgto.example-nsxpc-throws-error.ExampleXpc") service.remoteObjectInterface = NSXPCInterface(with: ExampleXpcProtocol.self) service.activate() guard let proxy = service.remoteObjectProxy as? any ExampleXpcProtocol else { return } defer { service.invalidate() } proxy.performCallback { callbackResult = "Done" } } Text(callbackResult) ... } } } callee (closure version) @objc protocol ExampleXpcProtocol { func performCallback(with reply: @escaping () -> Void) } class ExampleXpc: NSObject, ExampleXpcProtocol { @objc func performCallback(with reply: @escaping () -> Void) { reply() } } I found this problem can be solved by receiving asynchronous using Swift Concurrency. caller (async version) struct ContentView: View { @State var callbackResult: String = "Waiting…" var body: some View { Form { Section("Run XPC Call with no argument and no return value using callback") { Button("Run…") { simpleAsyncResult = "Running…" Task { let service = NSXPCConnection(serviceName: "net.mtgto.example-nsxpc-throws-error.ExampleXpc") service.remoteObjectInterface = NSXPCInterface(with: ExampleXpcProtocol.self) service.activate() guard let proxy = service.remoteObjectProxy as? any ExampleXpcProtocol else { return } defer { service.invalidate() } await proxy.performNothingAsync() simpleAsyncResult = "DONE" } Text(simpleAsyncResult) ... } } } callee (async version) @objc protocol ExampleXpcProtocol { func performNothingAsync() async } class ExampleXpc: NSObject, ExampleXpcProtocol { @objc func performNothingAsync() async {} } To simplify matters, I write source code that omits the arguments and return value, but it is not also invoked by using callback style. All sample codes are available in https://github.com/mtgto/example-nsxpc-throws-error
Posted
by
Post marked as solved
16 Replies
492 Views
Hello Apple Developer Community, I'm encountering an issue with my macOS application where I'm receiving the following error message: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.FxPlugTestXPC was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.FxPlugTestXPC was invalidated: failed at lookup with error 159 - Sandbox restriction.} This error occurs when my application tries to establish a connection to an XPC service named com.FxPlugTestXPC. It appears to be related to a sandbox restriction, but I'm unsure how to resolve it. I've checked the sandboxing entitlements and ensured that the necessary permissions are in place. However, the issue persists. Has anyone encountered a similar error before? If so, could you please provide guidance on how to troubleshoot and resolve this issue? Any help or insights would be greatly appreciated. Thank you. this is some photos about my entitlements :
Posted
by
Post not yet marked as solved
2 Replies
192 Views
I have an application, it has main process and some child processes. As we want those child processes to have their own minimum sandbox privilege, not inheriting from parent process, we plan to use XPCService which uses a NSTask to launch those child processes, so those child processes can have its own sandbox privilege. We plan to deliver the application to Mac App Store, so process mode is: the sandboxed main process builds connections to the unsandboxed XPCService, the unsandboxed XPCService launch those sandboxed child processes. Can this process mode pass the Mac App Store rules? I see, there is a rule that all processes must be sandboxed, including XPCService. But I tested locally, the Application downloaded from Mac apple store also launches unsandboxed XPCService, like OneDrive. Do you have any suggestions for my application scenario, sandboxed child processes having its own privilege not inheriting from parent?
Posted
by
Post not yet marked as solved
2 Replies
169 Views
I've been experimenting with the new low-level Swift API for XPC (XPCSession and XPCListener). The ability to send and receive Codable messages is an appealing alternative to making an @objc protocol in order to use NSXPCConnection from Swift — I can easily create an enum type whose cases map onto the protocol's methods. But our current XPC code validates the incoming connection using techniques similar to those described in Quinn's "Apple Recommended" response to the "Validating Signature Of XPC Process" thread. I haven't been able to determine how to do this with XPCListener; neither the documentation nor the Swift interface have yielded any insight. The Creating XPC Services article suggests using Xcode's XPC Service template, which contains this code: let listener = try XPCListener(service: serviceName) { request in request.accept { message in performCalculation(with: message) } } The apparent intent is to inspect the incoming request and decide whether to accept it or reject it, but there aren't any properties on IncomingSessionRequest that would allow the service to make that decision. Ideally, there would be a way to evaluate a code signing requirement, or at least obtain the audit token of the requesting process. (I did notice that a function xpc_listener_set_peer_code_signing_requirement was added in macOS 14.4, but it takes an xpc_listener_t argument and I can't tell whether XPCListener is bridged to that type.) Am I missing something obvious, or is there a gap in the functionality of XPCListener and IncomingSessionRequest?
Posted
by
Post not yet marked as solved
4 Replies
208 Views
We are working on a command line daemon (started with launchd) for a UI to communicate with using XPC. The functions we have been using so far work correctly, but they only take arguments and return void. We wanted to add a function with a simple reply block to see if the daemon is running or not, and we may need to get data back in the future. But it is not working. For example, this is working: if let proxy = connectionToService.remoteObjectProxyWithErrorHandler({ error in print(error.localizedDescription) }) as? TheDaemonProtocol { proxy.doStuff("Test string") } But this returns an error "Couldn’t communicate with a helper application." if let proxy = connectionToService.remoteObjectProxyWithErrorHandler({ error in print(error.localizedDescription) }) as? TheDaemonProtocol { proxy.isUp { reply in print("reply: \(reply)") } } isUp() is coded to only return true for now. @objc func isUp(reply: @escaping (Bool) -> Void) { reply(true) } TIA for any help!
Posted
by
Post marked as solved
2 Replies
195 Views
I'm working on a macOS application that deals with a few external dependencies that can only be compiled for intel (x86_64) but I want the app to run natively on both arm and x86_64. One idea I have been playing with is to move the x86_64 dependencies to an xpc service compiled only as x86_64 and use the service only the intel machine. However, I can't figure out how to setup my project to compile everything at once... Any ideas? Is this even possible? If not, I'm open to suggestions... Thanks
Posted
by
Post not yet marked as solved
0 Replies
302 Views
Greetings! I've added a Matter accessory via the Apple Home app. In my app, I'm attempting to commission this device and add it to my fabric. However, when I try to open the commissioning window, I receive an error stating, MTRBaseDevice doesn't support openCommissioningWindowWithDiscriminator over XPC. It appears that opening a commissioning window via an XPC connection is not yet supported. Is there another method to commission the device? Can I retrieve the setup payload from the MTRBaseDevice object or the shared MTRDeviceController? Here's the simplified version of my code: var home: HMHome // HMHome received via HMHomeManager var accessory: HMAccessory = home.accessory[0] // my Matter-supported accessory let deviceController = MTRDeviceController.sharedController( withID: home.matterControllerID as NSCopying, xpcConnect: home.matterControllerXPCConnectBlock ) let device = MTRBaseDevice( nodeID: accessory.matterNodeID as NSNumber, controller: deviceController ) device.openCommissioningWindow( withDiscriminator: 0, duration: 900, queue: .main) { payload, error in if let payload { // payload not received } else if let error { // I'm getting here "Error Domain=MTRErrorDomain Code=6 "(null)"" // and "MTRBaseDevice doesn't support openCommissioningWindowWithDiscriminator over XPC" logged in the console print(error) }
Posted
by
Post not yet marked as solved
0 Replies
402 Views
I am currently working on planning a multi-component software system that consists of an Audio Server Plugin and an application for user interaction. I have very little experience with IPC/XPC and its performance implications, so I hope I can find a little guidance here. The Audio Server plugin publishes a number of multi-channel output devices on which it should perform computations and pass the result on to a different Core Audio device. My concerns here are: Can the plugin directly access other CoreAudio devices for audio output or is this prohibited by the sandboxing? If it cannot, would relaying the audio data via XPC be a good idea in terms of low latency stability? Can I use metal compute from within the Audio Server plugin? I have not found any information about metal related sandboxing entitlements. I am also concerned about performance implications as above. Regarding the user interface application, I would like to know: If a process that has not been started by launchd can communicate with the Audio Server plugin using XPC. If not, would a user agent instead of an app be a better choice? Or are there other communication channels that would work with sandboxing? Thank you very much! Andreas
Posted
by
Post not yet marked as solved
1 Replies
335 Views
I want to build an Xcode Source Code Editor extension that triggers an XPC service shows a gui that can handle user interactions Is it possible in any way ? what are the alternatives to display the UI and allow the user to interact on it ?
Posted
by
Post not yet marked as solved
3 Replies
382 Views
Hello, we are currently working on a plan to migrate our app suite from Developer ID binaries inside a simple pkg installer to macOS app store distribution. The reason we are using an installer is that there are multiple binaries inside that communicate via XPC and we need to install the respective launchd plist in /Library/LaunchDaemons and /Library/LaunchAgents: 1 root daemon 1 agent that has minimal UI and lives in the system menu bar 1 embedded command line utility in user agent 1 embedded FileProvider extension in user agent 1 embedded Action Extension in user agent 1 agent that only does OAuth stuff Looking through Updating helper executables from earlier versions of macOS I can install the root daemon with SMAppService.daemon(plistName:) and the OAuth helper with SMAppService.agent(plistName:). For the main application I only found SMAppService.mainApp which does not accept a property list configuration. Therefore, I have no place to put my MachServices array and so the File Provider extension, the Action Extension, and the embedded command line utility have no way to talk to the user agent. Currently, XPC is used in between these processes: user agent -> root daemon command line utility -> user agent action extension -> user agent file provider extension -> user agent user agent -> file provider extension: that already works through NSFileProviderServicing I know app-to-app communication only works through launchd for security reasons, but these applications are all part of the same app group (except the root daemon obviously). My question is what is the proper way of starting the user agent so XPC from other binaries just work ™️? Any input is much appreciated!
Posted
by
Post not yet marked as solved
12 Replies
584 Views
I asked a similar question last year, and got no responses. I've written a much simpler (no network extension!) case that seems to demonstrate what I'm confused about. Simple app with an XPC service. I have an ObjectiveC class TestObject which has an NSString* and an NSData* (which I never actually use). I have a protocol defined in Swift: @objc protocol XPCTestServiceProtocol { func logData(entry: TestObject) -> Void func logData(entry: TestObject, completion: ((String) -> Void)) } In the Switt XPC service, the code is: class XPCTestService: NSObject, XPCTestServiceProtocol { var totalBytes = 0 var lastName = "" @objc func logData(entry: TestObject) { totalBytes += (entry.data?.count ?? 0) } @objc func logData(entry: TestObject, completion: ((String) -> Void)) { totalBytes += (entry.data?.count ?? 0) completion("Finished") } I've got this code in the ObjC app: id<XPCTestServiceProtocol> proxy = [self.connection remoteObjectProxyWithErrorHandler:^(NSError* error) { self.stopRun = YES; NSLog(@"Proxy got error %@", error); }]; while (self.stopRun == NO) { @synchronized (self) { NSNumber *objNum = [NSNumber numberWithUnsignedLongLong:self.count++]; NSString *objName = [NSString stringWithFormat:@"Object %@", objNum]; TestObject __weak *toWeak = to; #if USE_COMPLETION [proxy logDataWithEntry:to completion:^(NSString *str) { to = nil; }]; #else [proxy logDataWithEntry:to]; #endif } } attached to a start button (and self.stopRun is set by a stop button, this is all super simple). So I run that, start the test, and things start going (122k calls/second it says). According to Activity Monitor, my app is using about 1gbyte after 20 seconds or so. However, if I run it under Instruments' Leaks template... Activity Monitor says it's used only about 60mbytes. (And at the end of the run, Instruments says it's used about 30mbytes.) Now... if I use the completion and a synchronous proxy, then even without Instruments, Activity Monitor says it's 60mbytes or so. Is the memory reported by Activity Monitor real? Or not real?
Posted
by
Post not yet marked as solved
23 Replies
1.1k Views
Hi there :) I try to put an Xcode project in place within a LaunchAgent. The ultimate goal is to have an "application" with two component: macOS application with just an basic UI all the logic happens in a LaunchAgent that runs on background and is launch at startup. The macOS app uses XPC to send messages to the agent that will run either the app is opened or not. I struggled at first having this error (for the agent): An XPC Service cannot be run directly. Then I found using MachServices key in the .plist of the agent fixes the issue, plus: let listener = NSXPCListener.init(machServiceName: "com.tonygo.NetworkMonitorAgent") Then I wonder: Do we have somewhere a documentation about how to setup a LaunchAgent in Xcode I create the plist of the agent on side and run it manually, I could do this in a more automatic way How could I package a macOS applciation that will contains the agent, install it and load the agent? Note: This is mainly for learning and understanding what we could do at each level (XPCService, LaunchAgents, LaunchDaemon, etc.).
Posted
by
Post marked as solved
5 Replies
495 Views
Hi everyone :) I'm exploring XPC these days; more specifically, I'm trying to establish a connection between a macOS application and an XPC service. I succeeded in establishing the connection, but now I'm trying to verify the incoming connection by using SecCodeCopyGuestWithAttributes, passing it an audit token. But I got the following error: 2024-01-18 10:43:06.805435+0100 DemoService[1627:7118397] [logging-persist] cannot open file at line 46922 of [554764a6e7] 2024-01-18 10:43:06.805452+0100 DemoService[1627:7118397] [logging-persist] os_unix.c:46922: (0) open(/private/var/db/DetachedSignatures) - Undefined error: 0 Cannot get SecCode: 100001 - UNIX[Operation not permitted] Audit token: Optional(32 bytes) The last two lines come from my code: class XPCClientValidator { var secCodeOptional: SecCode? = nil; func identifyGuest(for connection: NSXPCConnection) -> Bool { let auditToken = AuditToken.extractToken(from: connection) let hostSecCode: SecCode? = nil; // This is a way to indicate that the code signing root of trust hould be used as host. let attributes = [ kSecGuestAttributeAudit: auditToken ] as CFDictionary let secFlags = SecCSFlags(rawValue: 0) // Asks a code host to identify the guest given the audit token let status: OSStatus = SecCodeCopyGuestWithAttributes(hostSecCode, attributes, secFlags, &self.secCodeOptional) if (status != errSecSuccess) { let msg = SecCopyErrorMessageString(status, nil)! print("Cannot get SecCode: \(status) - \(msg)") print("Audit token: \(String(describing: auditToken))") return false } guard let _ = secCodeOptional else { NSLog("Couldn't unwrap the secCode") return false } return true } } I saw a few posts on the forum, but nothing helped me to solve this issue. The complete source code is here: https://github.com/tony-go/XPCDemo/tree/secure-xpc Note: If you want to reproduce it, you have to: start the app type a random input click on "uppercase it"
Posted
by
Post not yet marked as solved
3 Replies
528 Views
I am looking for a solution to transfer data between two completely separate processes (not from the same group). I did a lot of research, but the solutions were mostly for processes that are in a group. Is there a method? (It doesn't matter if the app is sandboxed, I can disable it). My goal is to communicate between a bundle(plugin) that is activated on the Mac login page and an XPC service and transfer data from the service to the bundle.
Posted
by
Post not yet marked as solved
2 Replies
424 Views
Hi Team, I have a Network Extension application and UI frontend for it. The UI frontend talks to the Network Extension using XPC, as provided by NEMachServiceName. On M2 machine, The application and XPC connection works fine on clean installation. But, when the application is upgraded, the XPC connection keeps failing. Upgrade steps: PreInstall script kills the running processes, both UI and Network Extension Let installation continue PostInstall script to launch the application after installation complete. Following code is successful to the point of resume from UI application NSXPCInterface *exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(IPCUIObject)]; newConnection.exportedInterface = exportedInterface; newConnection.exportedObject = delegate; NSXPCInterface *remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(IPCExtObject)]; newConnection.remoteObjectInterface = remoteObjectInterface; self.currentConnection = newConnection; [newConnection resume]; But it fails to get the object id<IPCExtObject> providerProxy = [self.currentConnection remoteObjectProxyWithErrorHandler:^(NSError *registerError) { }]; Please note, this only fails for M2. For M1, this exact code is running fine. Additionally, if I uninstall the application by dropping it in Trash and then installing the newer version, then too, the application works fine.
Posted
by
Post not yet marked as solved
7 Replies
778 Views
I’m trying to implement XPC Rendezvous like Quinn described in many awesome posts on here but I’m now at a stuck point were I just have no idea. I want to communicate with a Safari extension via XPC and also a helper application which led me to XPC Rendezvous (https://developer.apple.com/forums/thread/715338) because a XPC Service in the Extension is scoped to the container. I then made a Command Line Target and added it like its described here (https://developer.apple.com/documentation/xcode/embedding-a-helper-tool-in-a-sandboxed-app ) and also took the xpc test code and inspiration to set up my launch agent from here (https://developer.apple.com/documentation/servicemanagement/updating_your_app_package_installer_to_use_the_new_service_management_api). This command line tool should do the management for the XPC connections because it’s not in the sandboxed container. The tool sets up the xpc connection like in the sample code directly and not in a XPC Service added via a Target template. It exposes the Mach Service. And that looks like its building fine after some fighting but the service just wont start - I saw it trying in console and after running it in Xcode and finally finding the crash report - it brought me there (https://developer.apple.com/forums/thread/706390) I have Process is not in an inherited sandbox. - and thinking about it, it makes sense because I first thought its just because it ran through Xcode, but its crashing this way also as a LaunchAgent. I mean it does make sense - there is nothing to inherit because it’s spawned by launchd - and that’s what I want isn’t it - to make the Rendezvous? Okay I thought now removing com.apple.security.inherit brings it in its own Sandbox (its needs sandboxing) but this also crashes the process because of the sandbox. Also after adding it to the App Group. What am I missing here or what do I want to accomplish? Do I want to inherit the sandbox? I guess not the helper should have its own. The only difference I see in comparison to SMAppServiceSampleCode is it moves the product in Copy Bundle Resources, and I have a Copy Files Phase with Destination: Executables (Like the other sample code said - and that’s looks “more correct” - and well SMAppServiceSampleCode isn’t sandboxed. I then tried making a new Command Line Target and just added App Sandbox Capability and tried to run this fresh one - and that also crashes. This makes me think I’m just ****** somewhere but I have read now everything I could find. I’m happy to provide any Code or crash logs but I dont know what part is really relevant here, It looks like the LaunchAgent gets installed correctly and wants to run but the sandbox is preventing me. The Bundle Identifier and XPC device name of the helper starts with my teamID (I got that from here https://developer.apple.com/forums/thread/703702) What could I be doing wrong? Thanks a lot! Benjamin
Posted
by
Post not yet marked as solved
1 Replies
379 Views
I would like to develop a macOS application in Swift. This application will consist of 2 programs: a main program to be run by the user (standard account) and another one that will run with root privileges. The second program will only be invoked to perform privileged tasks. Running the main program under root permanently would be too risky. XPC will be used to trigger calls from the main program to the privileged program. How can I secure the privileged program to ensure that the calling program is indeed my main program and not another unauthorized program?
Posted
by
Post not yet marked as solved
2 Replies
921 Views
Development Environment: Xcode Version: 14.3.1 macOS Ventura Version: 13.6.2 Architecture: Intel I am developing a macOS app with an accompanying XPC service and am encountering an issue where the XPC connection is immediately invalidated upon trying to establish it. The error message received is: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.appname.macos.app-name-xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.appname.macos.app-name-xpc was invalidated: failed at lookup with error 3 - No such process.} Here's what I have verified so far: The XPC service has the correct CFBundleIdentifier and is located within the Contents/XPCServices directory of my app's bundle. Info.plist for the XPC service has ServiceType set to Bundled. The XPC service target's Installation Directory is the default location for XPC services (@executable_path/../XPCServices). Code signing and entitlements have been verified for both the main app and the XPC service, and disabling the sandbox doesn't resolve the issue. The main app and XPC service are part of the same App Group, and both have the App Sandbox capability enabled. Here's a snippet of the Swift code that establishes the XPC connection: let xpcConnection = NSXPCConnection(serviceName: "com.appname.macos.app-name-xpc") xpcConnection.remoteObjectInterface = NSXPCInterface(with: ServiceProtocol.self) xpcConnection.resume() And here's the ServiceProtocol for reference: @objc public protocol ServiceProtocol: NSObjectProtocol { @objc func executeUnixExecutable(arguments: [String], completionHandler: @escaping (ResultType) -> Void) func interruptUnixExecutable() func closeUnixExecutablePipes() } When I run the app, the connection is invalidated without any further details as to why. I'm not sure if I'm missing a configuration step or if there's an issue with my XPC service setup. Has anyone experienced this issue or have suggestions on what else I can check to resolve this?
Posted
by