I have a Mac OS remote application that is made out of three parts.
1.- A LaunchDaemon that handles all of my network code and connects to my client
2.- A LaunchAgent to provides access to the window server to capture monitors, events, etc.
3.- A NSApplication to allow the user to control the LaunchDaemon
I'm trying to get the LaunchAgent and LaunchDaemon to run only while my NSApp is running.
LaunchDaemon - it uses machServices so I "control" it by starting an xpcConnection from my NSApplication.
LaunchAgent - it uses QueueDirectories and I start it by having my NSApplication save a file to the QueueDirectories path.
My NSApp and LaunchAgent both communicate with the LaunchDaemon via XPCConnection. Everything works as expected until I try quit my NSApp, LaunchDaemon and LaunchAgent. This is how I do it.
User quits NSApp -> NSApp removes QueueDirectory file, sends a quit message to Daemon and it gets terminated -> Daemon sends a message to Agent then it terminates with exit(0) -> Agent receives the message and it terminates with exit(0) as well.
Agent gets terminated and immediately launches again creating demand for my Daemon and starting it again.
When I run launchctl blame on my Agent I get xpc event. which means that the xpc connection with my daemon is still creating demand somehow even after calling .invalidate() and deallocating the connection object.? Is there a specific way to terminated an XPCConnection?
this is how I create my XPCConnectionListener:
NSXPCListener(machServiceName: "myMachServiceName")
and my connections
let connection = NSXPCConnection("myMachServiceName", options: [.privileged])
connection.remoteObjectInterface = NSXPCInterface(with: myProtocol.self)
connection.exportedInterface = NSXPCInterface(with: myProtocol.self)
connection.exportedObject = exportedObject
connection.interruptionHandler = interruptionHandler
connection.invalidationHandler = invalidationHandler
return connection
So it seems that the issue is that my connections aren't fully terminated when I quit the processes? any pointers would be greatly appreciated.
When I run
launchctl blame
on my Agent I getxpc event
which means that the xpc connection with my daemon is still creating demand somehow … ?
That’s unlikely. I believe that xpc event
is a referring to the general mechanism we use to start jobs other than via IPC demand. There is a supported interface, into this documented in xpc_events
man page, but it’s also used under the covers.
In the standard case, where your agent was launched by QueueDirectories
, what does launchctl blame
say? I suspect it’ll say xpc event
in that case as well.
Coming back to the bigger picture, given that your app is running in the same GUI login context as your agent, why are you using QueueDirectories
? Standard practice here is to have the agent publish its own named XPC endpoint and then have your app start the agent by messaging that.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"