How to debug a Launch Daemon that requires an App Group provisioning profile for XPC communication

Hello,

I am developing a macOS Launch Daemon (packaged as a bundle) that acts as an XPC server. For debugging purposes, I am trying to run the daemon's executable directly from the terminal via sudo ./mydaemon.app/Contents/MacOS/myexecutable.

Initially, I added the com.apple.security.application-groups entitlement to the daemon. However, when starting the process, it failed to create the XPC service with the following errors:

Unsatisfied entitlements: com.apple.security.application-groups Soft-restriction provisioning profile validation failure: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=<private>, unsatisfiedEntitlements=<private>, NSLocalizedDescription=No matching profile found}

listener failed to activate: xpc_error=[1: Operation not permitted]

To resolve the profile validation failure, I registered a new App Group in the Apple Developer Portal, generated a new provisioning profile for the daemon that includes this group, and embedded it into the bundle (Contents/embedded.provisionprofile).

Now, the previous profile error is gone, but I am getting a new identity conflict error, and the XPC listener still fails:

Two equal instances have unequal identities. <anon<myproc_name>(501) pid=2818 AUID=501> and <anon<myproc_name>(501)(262) pid=2818 AUID=262> listener failed to activate: xpc_error=[1: Operation not permitted]

My questions are:

What exactly causes the Two equal instances have unequal identities error? I noticed the Audit UID difference (AUID=501 vs AUID=262). Why does NSXPCListener still fail with Operation not permitted? What is the recommended workflow for debugging a Launch Daemon that requires an App Group provisioning profile for XPC communication?

Thank you in advance!

Answered by DTS Engineer in 882389022
For debugging purposes, I am trying to run the daemon's executable directly from the terminal

This won’t work. For your launchd daemon to work correctly, it must be started by launchd. I explain why that’s the case in XPC and App-to-App Communication.

My general advice for debugging a launchd daemon is:

  • Structure your code so that you can do most of your debugging in unit tests, rather than in your daemon. That’ll make your life much easier.
  • To unit test your XPC code, use the technique in TN3113 Testing and debugging XPC code with an anonymous listener.
  • To debug integration issues:
    • Using LLDB’s --wait-for option to attach to the daemon shortly after it starts. There’s a similar option in Xcode, under Debug > Attach to Process by PID or Name.
    • Or if you absolutely need to debug from the first instruction, add the WaitForDebugger property to your launchd property list. See the launchd.plist man page for details.
To resolve the profile validation failure …

Right. For the record, this approach is documented in Signing a daemon with a restricted entitlement.

Share and Enjoy

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

For debugging purposes, I am trying to run the daemon's executable directly from the terminal

This won’t work. For your launchd daemon to work correctly, it must be started by launchd. I explain why that’s the case in XPC and App-to-App Communication.

My general advice for debugging a launchd daemon is:

  • Structure your code so that you can do most of your debugging in unit tests, rather than in your daemon. That’ll make your life much easier.
  • To unit test your XPC code, use the technique in TN3113 Testing and debugging XPC code with an anonymous listener.
  • To debug integration issues:
    • Using LLDB’s --wait-for option to attach to the daemon shortly after it starts. There’s a similar option in Xcode, under Debug > Attach to Process by PID or Name.
    • Or if you absolutely need to debug from the first instruction, add the WaitForDebugger property to your launchd property list. See the launchd.plist man page for details.
To resolve the profile validation failure …

Right. For the record, this approach is documented in Signing a daemon with a restricted entitlement.

Share and Enjoy

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

How to debug a Launch Daemon that requires an App Group provisioning profile for XPC communication
 
 
Q