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

Posts under XPC tag

200 Posts

Post

Replies

Boosts

Views

Activity

sysext crashed while sending lots of log to host app
hi all. I subscribe the notify write event, every time I recieve a notify write event message i will send log data and reply block(didn't do nothing) with async method to host app(Objc XPC API).host app will reply immediately once it recieves data. after a while my sysext crashed, then I checked system log find the log below. launchd: exited with exit reason (namespace: 30 code: 0xc40000000004aaaa) - (unknown reason) is it because of exceeding the maximum limit of xpc's block queue length, or too many memory allocation, or... by the way, host app didn't crash. how this happened exactly? how could i solve it?
4
0
1.3k
Jun ’24
How do you allow an XPC service to create a new file based on an NSURL that the user selected from an NSSavePanel?
How do you send an NSURL representing a new file, as returned from an NSSavePanel, to an XPC service such that the service is granted permission to create the file? I can successfully pass an NSURL to the XPC process if the NSURL represents an existing file. This is documented in Apple's Documentation: Share file access between processes with URL bookmarks This involves creating bookmark date while passing 0 in as the options. However, if you try to create bookmark data for an NSURL that represents a file that is not yet created, you do not get any bookmark data back and an error is returned instead: Error Domain=NSCocoaErrorDomain Code=260 "The file couldn’t be opened because it doesn’t exist." Simply passing the file path to the XPC process, by way of: xpc_dictionary_set_string(message, "file_path", url.fileSystemRepresentation); Does not grant the XPC create/write permissions. Is there an API or trick I'm missing? Note that the user should be allowed to save and create new files anywhere of their choosing, thus restricting URLs to only those within a group or container shared between the app and service isn't really viable. Using the latest of everything on macOS with the xpc_session API...
1
0
1.1k
Jun ’24
FileHandle over XPC failure?
2024-06-04 15:17:59.618853+0100 ProxyAgent[20233:29237510] [xpc.exceptions] <NSXPCConnection: 0x60000331cb40> connection from pid 20227 on anonymousListener or serviceListener: Exception caught during decoding of received selector newFlowWithIdentifier:to:type:metadata:socket:, dropping incoming message. Exception: Exception while decoding argument 4 (#6 of invocation): <NSInvocation: 0x600001778780> return value: {v} void target: {@} 0x0 selector: {:} null argument 2: {@} 0x6000017787c0 argument 3: {@} 0x60000002d170 argument 4: {q} 1 argument 5: {@} 0x600001746600 argument 6: {@} 0x0 Exception: decodeObjectForKey: Object of class "NSFileHandle" returned nil from -initWithCoder: while being decoded for key <no key> The extension is in Swift; the recipient is in ObjC (wheeeeee). Based on the extension's logging, the FileHandle is not nil. I am trying to pass a FileHandle based on a socketpair up to the user-land code. The sockets are created happily. Any ideas what's going wrong here?
5
0
900
Jun ’24
XPC, Swift, ObjC, and arrays
I create a protocol that had, among other things: @objc func setList(_: [MyType], withReply: @escaping (Error?) -> Void) The daemon part is in Swift, while the calling part is in Objective-C. Because why not? (Actually, because the calling part has to deal with C++ code, so that's ObjC++; however, I wanted the stronger typing and runtime checking for the daemon part, so I wrote it in Swift.) The ObjC part uses NSArray<MyType*>. I set up an NSXPCConnection link, and create a (synchronous) proxy with the right protocol name. But when I try to do the XPC setList call, I get an error. I assume that's because it doesn't like the signature. (Surely this is logged somewhere? I couldn't find it, if so. 😩) But... if I have a signature of @objc func addItem(_: MyType, withReply: @escaping (Error?) -> Void), then it works. So I assume it's the array. (Oh, I've also tried it without the @objc; the protocol itself is defined as @objc.) I've tried changing to protocol signature to using NSArray, but same thing.
7
0
2.1k
Jun ’24
`listener failed to activate: xpc_error=[1: Operation not permitted]`
Hi :wave: I started a new project to experiment with EndpointSecurity framework. It seems to have been worked, but when I try to add XPC I face some troubles. I am not able to send XPC message from my app to my system extension. No runtime error, but when I'm inspecting logs: That correspond to this code: https://github.com/tony-go/TestES/blob/main/Extension/main.swift#L21-L30 Full project: https://github.com/tony-go/TestES/ I thought at first that it could come from a missing @objc somehere but it does not seems ... I also wonder why I cannot catch this error at runtime ?
12
0
3k
Jun ’24
How to check XPCConnection is REALLY connected
I'm using XPC to do IPC with an agent service. I use NSXPCConnection initWithMachServiceName to create the connection and active it. Then I get the agent service remote object proxy with method remoteObjectProxyWithErrorHandler. But when the agent service unloaded, I can also get the remote proxy without any error. Is there anyway to check XPCConnection really connect to a XPC server?
1
0
925
May ’24
App sandbox extension revoked on Ventura
Hi everyone, first-time caller, long-ti... wait, no, I just got here. :) I am relatively new to all things Apple, so apologies in advance if it takes me a few goes to properly explain things. We have a framework, which includes an API, an XPC service, etc, and we have a device driver. We also have some sample apps that use the framework, and if they have the app sandbox capability, then we expect them to use the XPC Service instead of accessing our driver directly. This works fine on Monterey and presumably has worked fine on all previous versions of MacOS. Something seems to have changed on Ventura, and we don't understand what. When we build the same app on Ventura, it appears to be in the sandbox (according to the Sandbox column in Activity Monitor), but in the Console there is this line (twice): default <time> <OurAppName> Revoking sandbox extension; key = 0 Which we suspect is linked to the fact that the app then does not use the XPC Service, and instead accesses the driver directly, much to our surprise. Software built on developer's machines is "Automatically managed" and "Signed to Run Locally" in case that matters. Do we need to change our code to support Ventura and onward? Or is it a bizarre bug? Oh, I should say that I'm running the latest version of Ventura (13.6.7 as of writing) but not the latest Xcode (14.2 (14C18)) and CLI tools... can't remember how to find that version... Apple clang version 14.0.0 (clang-1400.0.29.202). Any help would be appreciated, thanks. Jeremy
6
0
1.3k
May ’24
Launching agent installed with SMAppService
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!
1
0
1.3k
Apr ’24
Error 159 - Sandbox restriction when connecting to XPC service
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 :
16
0
5.5k
Apr ’24
Callback is not invoked when a closure callback-style call is executed in XPC
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
2
0
1.2k
Apr ’24
XPC Service Connection Invalidated Immediately on Launch
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?
2
0
5.4k
Apr ’24
Unable to get function reply back from Mach XPC command line daemon
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!
4
0
909
Apr ’24
Compile XPC service with a different architecture than the client
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
2
0
847
Mar ’24
Swift Process with Psuedo Terminal (PTY)
Hi! I'm looking for some insight and guidance on using the Foundation.Process type with a PTY (Psuedo Terminal) so that the subprocess can accept input and behave as if it was running via a terminal. The reason for needing a PTY is that for programs like ssh or in my case (xcodes) which ask for user input including passwords, running these via Foundation.Process does not display the prompts to the user as the output is usually buffered (this works fine in the Xcode debugger console but when running via a real terminal that is buffered the prompts are never displayed in the terminal) Looking at other threads it seems like correct approach here is create a PTY and use the filehandles to attach to the Process. While I've got this to work to the point where prompts are now shown, I cant seem to figure out how to pass input back to the process as these are being controlled by the PTY. Here is my Process setup: let process = Process() // Setup the process with path, args, etc... // Setup the PTY handles var parentDescriptor: Int32 = 0 var childDescriptor: Int32 = 0 guard Darwin.openpty(&parentDescriptor, &childDescriptor, nil, nil, nil) != -1 else {   fatalError("Failed to spawn PTY") } parentHandle = FileHandle(fileDescriptor: parentDescriptor, closeOnDealloc: true) childHandle = FileHandle(fileDescriptor: childDescriptor, closeOnDealloc: true) process.standardInput = childHandle process.standardOutput = childHandle process.standardError = childHandle With this setup I then read the parent handle and output any result it gets (such as the input prompts): parentHandle?.readabilityHandler = { handle in   guard let line = String(data: handle.availableData, encoding: .utf8), !line.isEmpty else {     return   }   logger.notice("\(line)") } When process.run() is executed the program runs and I can see it asks for Apple ID: input in my terminal, however, when typing input into the terminal the process does not seem to react to this input. I've tried forwarding the FileHandle.standardInput: FileHandle.standardInput.readabilityHandler = { handle in   parentHandle?.write(handle.availableData) } But this doesn't seem to work either. What is the recommended way to setup a PTY with Foundation.Process for executing arbitrary programs and having them behave as if they were being run in a terminal context? Most of the resources I found online are about other languages and I'd like to stick with Foundation.Process vs. doing anything custom in C/C++ if possible as it just makes it easier to reason about / maintain. The resources for Swift on this topic are very lacking and I've checked out some open source projects that claim to do this but most require manually sending input to the PTY handle vs. accepting them from the user in a terminal. Any insight / help is very much appreciated!
9
0
4.6k
Mar ’24
Setup LaunchAgent in Xcode
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.).
23
0
4.3k
Feb ’24
Audio Server Plugin entitlements and communication
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
0
1
1.1k
Feb ’24
XPC, memory allocation, and much confusion
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?
12
0
1.7k
Feb ’24
sysext crashed while sending lots of log to host app
hi all. I subscribe the notify write event, every time I recieve a notify write event message i will send log data and reply block(didn't do nothing) with async method to host app(Objc XPC API).host app will reply immediately once it recieves data. after a while my sysext crashed, then I checked system log find the log below. launchd: exited with exit reason (namespace: 30 code: 0xc40000000004aaaa) - (unknown reason) is it because of exceeding the maximum limit of xpc's block queue length, or too many memory allocation, or... by the way, host app didn't crash. how this happened exactly? how could i solve it?
Replies
4
Boosts
0
Views
1.3k
Activity
Jun ’24
How do you allow an XPC service to create a new file based on an NSURL that the user selected from an NSSavePanel?
How do you send an NSURL representing a new file, as returned from an NSSavePanel, to an XPC service such that the service is granted permission to create the file? I can successfully pass an NSURL to the XPC process if the NSURL represents an existing file. This is documented in Apple's Documentation: Share file access between processes with URL bookmarks This involves creating bookmark date while passing 0 in as the options. However, if you try to create bookmark data for an NSURL that represents a file that is not yet created, you do not get any bookmark data back and an error is returned instead: Error Domain=NSCocoaErrorDomain Code=260 "The file couldn’t be opened because it doesn’t exist." Simply passing the file path to the XPC process, by way of: xpc_dictionary_set_string(message, "file_path", url.fileSystemRepresentation); Does not grant the XPC create/write permissions. Is there an API or trick I'm missing? Note that the user should be allowed to save and create new files anywhere of their choosing, thus restricting URLs to only those within a group or container shared between the app and service isn't really viable. Using the latest of everything on macOS with the xpc_session API...
Replies
1
Boosts
0
Views
1.1k
Activity
Jun ’24
FileHandle over XPC failure?
2024-06-04 15:17:59.618853+0100 ProxyAgent[20233:29237510] [xpc.exceptions] <NSXPCConnection: 0x60000331cb40> connection from pid 20227 on anonymousListener or serviceListener: Exception caught during decoding of received selector newFlowWithIdentifier:to:type:metadata:socket:, dropping incoming message. Exception: Exception while decoding argument 4 (#6 of invocation): <NSInvocation: 0x600001778780> return value: {v} void target: {@} 0x0 selector: {:} null argument 2: {@} 0x6000017787c0 argument 3: {@} 0x60000002d170 argument 4: {q} 1 argument 5: {@} 0x600001746600 argument 6: {@} 0x0 Exception: decodeObjectForKey: Object of class "NSFileHandle" returned nil from -initWithCoder: while being decoded for key <no key> The extension is in Swift; the recipient is in ObjC (wheeeeee). Based on the extension's logging, the FileHandle is not nil. I am trying to pass a FileHandle based on a socketpair up to the user-land code. The sockets are created happily. Any ideas what's going wrong here?
Replies
5
Boosts
0
Views
900
Activity
Jun ’24
Trying to learn more about xpc_session_t...
(Updated) See replies below.
Replies
2
Boosts
0
Views
976
Activity
Jun ’24
XPC, Swift, ObjC, and arrays
I create a protocol that had, among other things: @objc func setList(_: [MyType], withReply: @escaping (Error?) -> Void) The daemon part is in Swift, while the calling part is in Objective-C. Because why not? (Actually, because the calling part has to deal with C++ code, so that's ObjC++; however, I wanted the stronger typing and runtime checking for the daemon part, so I wrote it in Swift.) The ObjC part uses NSArray<MyType*>. I set up an NSXPCConnection link, and create a (synchronous) proxy with the right protocol name. But when I try to do the XPC setList call, I get an error. I assume that's because it doesn't like the signature. (Surely this is logged somewhere? I couldn't find it, if so. 😩) But... if I have a signature of @objc func addItem(_: MyType, withReply: @escaping (Error?) -> Void), then it works. So I assume it's the array. (Oh, I've also tried it without the @objc; the protocol itself is defined as @objc.) I've tried changing to protocol signature to using NSArray, but same thing.
Replies
7
Boosts
0
Views
2.1k
Activity
Jun ’24
`listener failed to activate: xpc_error=[1: Operation not permitted]`
Hi :wave: I started a new project to experiment with EndpointSecurity framework. It seems to have been worked, but when I try to add XPC I face some troubles. I am not able to send XPC message from my app to my system extension. No runtime error, but when I'm inspecting logs: That correspond to this code: https://github.com/tony-go/TestES/blob/main/Extension/main.swift#L21-L30 Full project: https://github.com/tony-go/TestES/ I thought at first that it could come from a missing @objc somehere but it does not seems ... I also wonder why I cannot catch this error at runtime ?
Replies
12
Boosts
0
Views
3k
Activity
Jun ’24
How to check XPCConnection is REALLY connected
I'm using XPC to do IPC with an agent service. I use NSXPCConnection initWithMachServiceName to create the connection and active it. Then I get the agent service remote object proxy with method remoteObjectProxyWithErrorHandler. But when the agent service unloaded, I can also get the remote proxy without any error. Is there anyway to check XPCConnection really connect to a XPC server?
Replies
1
Boosts
0
Views
925
Activity
May ’24
App sandbox extension revoked on Ventura
Hi everyone, first-time caller, long-ti... wait, no, I just got here. :) I am relatively new to all things Apple, so apologies in advance if it takes me a few goes to properly explain things. We have a framework, which includes an API, an XPC service, etc, and we have a device driver. We also have some sample apps that use the framework, and if they have the app sandbox capability, then we expect them to use the XPC Service instead of accessing our driver directly. This works fine on Monterey and presumably has worked fine on all previous versions of MacOS. Something seems to have changed on Ventura, and we don't understand what. When we build the same app on Ventura, it appears to be in the sandbox (according to the Sandbox column in Activity Monitor), but in the Console there is this line (twice): default <time> <OurAppName> Revoking sandbox extension; key = 0 Which we suspect is linked to the fact that the app then does not use the XPC Service, and instead accesses the driver directly, much to our surprise. Software built on developer's machines is "Automatically managed" and "Signed to Run Locally" in case that matters. Do we need to change our code to support Ventura and onward? Or is it a bizarre bug? Oh, I should say that I'm running the latest version of Ventura (13.6.7 as of writing) but not the latest Xcode (14.2 (14C18)) and CLI tools... can't remember how to find that version... Apple clang version 14.0.0 (clang-1400.0.29.202). Any help would be appreciated, thanks. Jeremy
Replies
6
Boosts
0
Views
1.3k
Activity
May ’24
How to make the app communicate with the camera extension?
I create a camera extension and App can push video data to camera extension with sinkStream. I want to monitor the number of clients connected to the camera extension and close the app's push stream when the number of connected client is zero.
Replies
3
Boosts
0
Views
1.2k
Activity
May ’24
Launching agent installed with SMAppService
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!
Replies
1
Boosts
0
Views
1.3k
Activity
Apr ’24
Error 159 - Sandbox restriction when connecting to XPC service
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 :
Replies
16
Boosts
0
Views
5.5k
Activity
Apr ’24
Callback is not invoked when a closure callback-style call is executed in XPC
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
Replies
2
Boosts
0
Views
1.2k
Activity
Apr ’24
XPC Service Connection Invalidated Immediately on Launch
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?
Replies
2
Boosts
0
Views
5.4k
Activity
Apr ’24
Unable to get function reply back from Mach XPC command line daemon
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!
Replies
4
Boosts
0
Views
909
Activity
Apr ’24
Compile XPC service with a different architecture than the client
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
Replies
2
Boosts
0
Views
847
Activity
Mar ’24
Swift Process with Psuedo Terminal (PTY)
Hi! I'm looking for some insight and guidance on using the Foundation.Process type with a PTY (Psuedo Terminal) so that the subprocess can accept input and behave as if it was running via a terminal. The reason for needing a PTY is that for programs like ssh or in my case (xcodes) which ask for user input including passwords, running these via Foundation.Process does not display the prompts to the user as the output is usually buffered (this works fine in the Xcode debugger console but when running via a real terminal that is buffered the prompts are never displayed in the terminal) Looking at other threads it seems like correct approach here is create a PTY and use the filehandles to attach to the Process. While I've got this to work to the point where prompts are now shown, I cant seem to figure out how to pass input back to the process as these are being controlled by the PTY. Here is my Process setup: let process = Process() // Setup the process with path, args, etc... // Setup the PTY handles var parentDescriptor: Int32 = 0 var childDescriptor: Int32 = 0 guard Darwin.openpty(&parentDescriptor, &childDescriptor, nil, nil, nil) != -1 else {   fatalError("Failed to spawn PTY") } parentHandle = FileHandle(fileDescriptor: parentDescriptor, closeOnDealloc: true) childHandle = FileHandle(fileDescriptor: childDescriptor, closeOnDealloc: true) process.standardInput = childHandle process.standardOutput = childHandle process.standardError = childHandle With this setup I then read the parent handle and output any result it gets (such as the input prompts): parentHandle?.readabilityHandler = { handle in   guard let line = String(data: handle.availableData, encoding: .utf8), !line.isEmpty else {     return   }   logger.notice("\(line)") } When process.run() is executed the program runs and I can see it asks for Apple ID: input in my terminal, however, when typing input into the terminal the process does not seem to react to this input. I've tried forwarding the FileHandle.standardInput: FileHandle.standardInput.readabilityHandler = { handle in   parentHandle?.write(handle.availableData) } But this doesn't seem to work either. What is the recommended way to setup a PTY with Foundation.Process for executing arbitrary programs and having them behave as if they were being run in a terminal context? Most of the resources I found online are about other languages and I'd like to stick with Foundation.Process vs. doing anything custom in C/C++ if possible as it just makes it easier to reason about / maintain. The resources for Swift on this topic are very lacking and I've checked out some open source projects that claim to do this but most require manually sending input to the PTY handle vs. accepting them from the user in a terminal. Any insight / help is very much appreciated!
Replies
9
Boosts
0
Views
4.6k
Activity
Mar ’24
Setup LaunchAgent in Xcode
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.).
Replies
23
Boosts
0
Views
4.3k
Activity
Feb ’24
Showing UI and Handling Click events using XPC Service
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 ?
Replies
1
Boosts
0
Views
984
Activity
Feb ’24
Audio Server Plugin entitlements and communication
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
Replies
0
Boosts
1
Views
1.1k
Activity
Feb ’24
XPC, memory allocation, and much confusion
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?
Replies
12
Boosts
0
Views
1.7k
Activity
Feb ’24