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

But this returns an error "Couldn’t communicate with a helper application."

What’s the error code?

This matters because, in XPC, you generally get one of two errors:

  • The interrupted error, like NSXPCConnectionInterrupted (4097)

  • The invalid error, like NSXPCConnectionInvalid (4099)

and the path forward depends on which one you got.


Also, just to check, are you running this code in an app? If so, is that app sandboxed? If so, try disabling the sandbox to see if that changes things.

The App Sandbox blocks unexpected outgoing XPC connections. There are ways to use XPC from a sandboxed app, but IMO it’s best to temporarily disable the sandbox during your bring up to rule it out as a cause of any problems you encounter.


Finally, XPC Resources has a bunch of useful XPC hints and tips.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks @eskimo. The error is NSXPCConnectionInterrupted (4097). The UI app is not sandboxed, it will be deployed with Developer ID for internal use. The call is coming from a SwiftUI Button action that the user taps on, and works correctly for functions that don't have a reply block.

Correction, we are now getting the NSCocoaErrorDomain Code=4099 error. But at some point yesterday it was 4097.

@eskimo I think I got it. NSXPCConnection invalidate() was being called too early in the client. Still have some learning to do for managing the connection state.