Allowing dynamic name registration in xpc_connection_create_mach_service

In the "Mach Services" section of the xpc_connection_create(3) man page, we have the following:

Important: New service names may NOT be dynamically registered using
xpc_connection_create_mach_service().  Only launchd jobs may listen on
certain service names, and any service name that the job wishes to listen
on must be declared in its launchd.plist(5).  XPC may make allowances for
dynamic name registration in debug scenarios, but these allowances abso-
lutely will NOT be made in the production scenario.

In a debugging scenario, how can I allow a dynamic name resolution for listeners? While the man page references this, it doesn't detail how to, and I can't find any information online about this. I can't tell if this text implies that it's currently possible, or may be allowed sometime in the future.

Answered by DTS Engineer in 732367022

running xpc_connection_create_mach_service does not work in a debug environment since the provided name is not found within the bootstrap namespace.

That’s interesting, but there are definitely circumstances where folks get mislead by Xcode’s behaviour.

However, I'm attempting to debug it by writing up a small "demo" program where I can easily debug and run the XPC listener code.

Are you trying to debug the XPC aspects of your code? If so, I recommend that you do this in a single process using an anonymous listener. See TN3113 Testing and debugging XPC code with an anonymous listener.

If you’re trying to debug other aspects of your launchd job, my advice is:

  • If the code does not need to run in the launchd context, factor it out into a unit test and debug it there.

  • If it does, start the code using launchd and attach to it. That’s the only way to ensure that the code is running in exactly the right context.

    In this case, check out WaitForDebugger in the launchd.plist man page.

Share and Enjoy

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

Shoot, I misnamed the thread. It should have been "Allowing dynamic name registration ..."

For a bunch of background on this, see XPC and App-to-App Communication.

The The Xcode Gotcha section touches on the same mechanics mentioned in that man page. It’s built-in to Xcode and there’s no supported way to replicate that behaviour in other environments.

Share and Enjoy

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

Thanks for the response! Your write-up provides a lot of great foundational understanding of XPC, and I appreciate the alternatives it provides. I'm not sure how "The Xcode Gotcha" section provides an answer to the question though. In fact, running xpc_connection_create_mach_service does not work in a debug environment since the provided name is not found within the bootstrap namespace.

I'm in the kind-of-opposite scenario basically: The app-to-app communication works normally because the listener is a launchd service (with the appropriate names filled in the MachService section of its info.plist file to allow clients to connect to it). However, I'm attempting to debug it by writing up a small "demo" program where I can easily debug and run the XPC listener code. The code calls xpc_connection_create_mach_service, but doesn't have any MachService names to work with, and a subsequent call to xpc_connection_resume causes an irrecoverable failure.

Accepted Answer

running xpc_connection_create_mach_service does not work in a debug environment since the provided name is not found within the bootstrap namespace.

That’s interesting, but there are definitely circumstances where folks get mislead by Xcode’s behaviour.

However, I'm attempting to debug it by writing up a small "demo" program where I can easily debug and run the XPC listener code.

Are you trying to debug the XPC aspects of your code? If so, I recommend that you do this in a single process using an anonymous listener. See TN3113 Testing and debugging XPC code with an anonymous listener.

If you’re trying to debug other aspects of your launchd job, my advice is:

  • If the code does not need to run in the launchd context, factor it out into a unit test and debug it there.

  • If it does, start the code using launchd and attach to it. That’s the only way to ensure that the code is running in exactly the right context.

    In this case, check out WaitForDebugger in the launchd.plist man page.

Share and Enjoy

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

That’s interesting, but there are definitely circumstances where folks get mislead by Xcode’s behaviour.

Agreed, and I definitely wouldn't be surprised if it was something weird with Xcode. Though in the same man page:

If the service name for the connection is not present in your launchd.plist's MachServices dictionary, your listener connection's event handler will receive the XPC_ERROR_CONNECTION_INVALID error, as XPC disallows ad-hoc service name registrations.

Which is the behavior I'm seeing. Though for some reason I also get an EXC_BAD_INSTRUCTION upon calling xpc_connection_resume.

Are you trying to debug the XPC aspects of your code? If so, I recommend that you do this in a single process using an anonymous listener. See TN3113 Testing and debugging XPC code with an anonymous listener.

At first, I wasn't sure how this would apply to me since you can't create anonymous listeners with xpc_connection_create_mach_service, but upon re-reading I realize that I could have replaced the listener connection with xpc_connection_create(NULL, ... following the techniques here, and that does the trick! Some refactoring is definitely in order.

While this doesn't explain dynamic name registration, it does ultimately resolve the issue I'm having. Thanks as always, Quinn!

Allowing dynamic name registration in xpc_connection_create_mach_service
 
 
Q