What is the correct way to self-terminate a MacOS XPC service?
Asked Answered
O

1

12

I've successfully followed the Daemons and Service Guide - Creating XPC Services tutorial, along with the SandboxedFetch sample code and have a working Client / Service setup that is using the new NSXPCConnection class.

What still isn't entirely clear to me is how to properly self-terminate the service application once it has finished its job. I recognize that in many cases, the service is expected to remain alive, but in the use-case I have in mind, the service will be used to only to do some processing that I'd otherwise not perform in the main application. Once that processing is finished, there's no reason for the service application to remain. If the client needs another service at a later date, it can just re-create a new one.

Since the service is a lightweight, non-nibbed, NSApplication, I was trying to self-terminate it by calling invalidate from inside applicationWillTerminate, but that triggers an EXC_BAD_ACCESS exception almost every time. Calling invalidate on the service's [NSXPCListener serviceListener] generates slightly less reliable crashes, but it still crashes.

Calling invalidate from within the client application on its NSXPCConnection also generates an EXC_BAD_ACCESS exception almost every time.

So I'm curious what the correct sequence of steps is to cleanly shutdown the XPC service and then quit the service application. Ideally, the service would self-terminate after it has made its last XPC call to the client.

Attached is a small screenshot of what one of the exception's stacktrace looks like. (Yes, that's a webview that's loading in the service. Once the webview has finished loading, I want the service to self-terminate)

enter image description here

Overpay answered 21/4, 2014 at 18:9 Comment(3)
Have you modeled your XPC service as a launch agent or similar? Regular XPC services should start and stop using launchd automatically when needed.Clearing
The XPC service I was using was an in-app XPC service launched using NSXPCConnection. I ultimately realized that even those services aren't meant to be explicitly terminated. The system will terminate them on an as-needed basis if they are idle.Overpay
So it does work, now that you stopped to worry about its lifetime management?Clearing
T
2

My first reaction is that you should not bother to terminate. When memory pressure occurs and your service is idle, launchd will kill your service. Exiting probably isn't in anyone's best interest because your service will take time to launch again. Don't terminate and you won't have to figure out why your attempt crashes.

But if for some reason you are determined to terminate, don't try so hard. Just do whatever you need to do to clean up (flush buffers, close network connections gracefully so the server doesn't suffer, whatever) and call exit. Although you seem to be using NSApplication, your service is not an application in any sense that the user cares about and there is no compelling reason to act like one in this respect. The host application needs to be able to cope with your service crashing anyway, so your deliberately exiting unceremoniously is just fine.

By the way, using NSApplication in an XPC service probably isn't the best idea because there's no supported way to declare that you want that. This might help explain why it isn't working as well as you'd like, though this paragraph should not be construed as a proper analysis of the crash. :-)

Torques answered 14/8, 2016 at 5:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.