Kill XPC when parent app is still running - kill

My parent application uses helper XPC to achieve some task T1. XPC service is implemented using NSXPCConnection.
Once the task is complete I don’t need this XPC to be alive. Hence, the parent process calls invalidate on NSXPCConnection object.
But, the XPC is still alive even if the connection is invalid. I can see it getting listed in Activity Monitor.
How do I kill this XPC when parent app is still running and it does not require XPC to be alive?

XPC Agents by design are meant to be long lived.
They automatically reload when they quit or crash based on their KeepAlive setting in the .plist configuration.
Maybe you can register as an Observer for NSWorkspace events:
[[NSWorkspace sharedWorkspace] notificationCenter];
see:
NSWorkspace
Workspace notifications are posted when:
applications are launched and terminated
Then you can disable your XPC Service When your Parent app quits and reenable it when it launches.

Just to be clear, your XPC process will quit when the parent app quits. At least, mine does. Your question is: How to kill it before then?
That is simple: Just call exit(0) in your XPC process immediately after it invokes the completion handler which sends the output back to the parent app. I needed to do this in a project last month, because the XPC process was using an Apple private framework, and exitting it was the only way I could figure to stop a certain undesired and inexplicable (since I have no documentation on the private framework) side effect.
Upon exitting this XPC process, however, I found that, oddly, it continued to run for some milliseconds, and if my parent app opened another connection to this same XPC service in the meantime, the doomed XPC process will accept the new connection just prior to killing itself, leaving the parent app hanging. I've actually seen this happen several times.
So, a follow-up question is: Should you kill it just because you want to be nice? I think the answer is no, according to the following quote from Apple's Daemons and Services Programming Guide > Creating XPC Services
XPC services are managed by launchd, which launches them on demand,
restarts them if they crash, and terminates them (by sending SIGKILL)
when they are idle.
To summarize: Just invalidate your connections when done, and let launchd worry about killing. Also, don't hold your breath. I've had my app running for the past two hours, and the XPC process, last connection closed two hours ago, is still running.

Related

Launchd flow of spawning new processes

I'm doing some research about the way launchd load it's services from plist files under /Library/LaunchDaemons/ or via the command launchctl load
So far I've managed to gather some various sources and compose the following vague picture as I understand it:
Upon Service loading (launchctl load) The process launchctl send the launchd an appropriate XPC message, and then the launchd is forked into new process with the context of xpcproxy.
This generic process, is waiting for another XPC call from the launchd to run it's real process context according to the launchDaemon plst.
Is this explanation sounds right ? perhaps anybody can help me make it more accurate ?
thanks
This is actually a bit more complicated. The kernel is composed of two parts, BSD and the mach kernel; the latter being responsible for management of memory and process scheduling.
Each mach process has one or more mach tasks (really task port rights!). When an application is first launched, it has just one right, the bootstrap port, allowing communication with launchd. Note that a task port right is uni-directional, so a launching process that has the right to communicate with launchd must give a right for launchd to communicate back to it.
When an XPC message is received by launchd, it depends upon the Launch Daemon as to what action it takes. It's possible that the message is for a service that runs with a network port that may or may not be running. If running, it forwards any arguments from the calling process to the running service. If not running, it can provide the service on demand by launching the process first.
More specifically you asked about launchctl load. Since the source code for launchd is no longer open source, the next best resource is the reverse engineering work by Jonathan Levin; Author of Mac OS X and iOS Internals and more recently, his newer self-published books on *OS Internals.
You'll find his slides about launchd here, but probably more useful to you is his version of launchctl, jlaunchctl which is open source.
Finally, if you want to view content of XPC messages between processes, disable SIP and use Jonathan's invaluable XPoCe tool.

Should I process WM_ENDSESSION, WM_QUERYENDSESSION, both or neither?

If a system is trying to shut down, an app can block this shutdown by overriding OnQueryEndSession() and returning FALSE. Surely that means WM_ENDSESSION is the only definitive message to respond to regarding shutdown.
On the other hand, the top answer to this question quotes no less than Raymond Chen as saying that responding to WM_ENDSESSION is essentially pointless. So this is confusing.
Is there some kind of "best practice" principles to apply in deciding which of these messages (if any) one should respond to for doing what kinds of application shutdown work?
In particular, if neither message is handled, will a shutdown process cause an application to be closed as if the user had closed the application manually (e.g. click on red X close button)?
This article from Microsoft gives a very comprehensive discussion of end-of-session best practice both pre- and post-Vista. The article makes it quite clear that one should assume that if one receives a WM_QUERYENDSESSION then shutdown will occur at some point.
As soon as all applications have responded to the WM_ENDSESSION message, or been forced to terminate within 5 seconds of receiving the WM_ENDSESSION message, Windows may shut down at any time. This may limit what can be done in response to WM_ENDSESSION.
If an application requires more time to clean itself up:
If your application may need more than 5 seconds to complete its shutdown processing in response to WM_ENDSESSION, it should call ShutdownBlockReasonCreate() in its WM_QUERYENDSESSION handler, and promptly respond TRUE to WM_QUERYENDSESSION so as not to block shutdown. It should then perform all shutdown processing in its WM_ENDSESSION handler.
Windows will apparently not send any additional messages to your application to allow it to exit "gracefully" (e.g. WM_CLOSE). Rather, it will simply call TerminateProcess. If you want a graceful close, you have to build it yourself within the above constraints.
You do need to close down your application in WM_ENDSESSION, at least if you want to support the Restart Manager API. I think both MSDN and Raymond are wrong here. (Maybe it changed recently, or they overlooked the Restart Manager?)
The Restart Manager API is used by installers to close and restart exes which have files locked that they need to replace. To support being restarted by it, you call RegisterApplicationRestart and then need to have a window which handles WM_QUERYENDSESSION and WM_ENDSESSION.
If you don't shut down your app in the WM_ENDSESSION handler than it will simply keep running and block the Restart Manager, and in turn the installers trying to use it.
I found this out the hard way. MSDN explicitly says you don't need to call PostQuitMessage, but if I don't do that then my process keep running.
I suspect the documentation didn't realise the Restart Manager is different, and less forceful, compared to what happens when the entire OS shuts down.
(Edit: I should add, this was with a simple ATL COM EXE server, but as far as I can tell there was nothing about that complicating things, and Windows simply wasn't triggering a WM_QUIT to the message loop unless I did it myself.)

How does OSX Activity Monitor match XPC tasks to their initiator process?

When an application process launches an XPC helper process, it doesn't actually do the fork()/exec() itself in the classic UNIX style. Instead, it sends a message to launchd, which does the dirty work for it. Thus, if you query the parent process on the XPC process, it comes back as the launchd process.
However, if you open Activity Monitor in the hierarchical process view, the XPC helper processes are all shown below the original application that requested them, for example:
In the software I'm working on, knowing this relationship between processes would be extremely useful. So far we've been using the regular BSD parent process information, but as everything moves towards XPC, this isn't much use anymore.
So:
Where is the "original" parent process information stored for XPC processes?
How does Activity Monitor access it?
There is a kext involved, so I'd be happy to pull this information straight out in the kernel instead of userspace, but I can't seem to even figure out where it's stored.
Update: Discussion on Apple's darwin-kernel mailing list: http://lists.apple.com/archives/darwin-kernel/2015/Mar/msg00001.html
I imagine that launchd knows what you are looking for.
The Service Management framework has a method that might give you what you are looking for easily.
CFDictionaryRef SMJobCopyDictionary(CFStringRef domain, CFStringRef jobLabel); function.

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

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)
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. :-)

C# catch kill command

how can I catch windows taskkill command in order to prevent it?
You cannot prevent your process being killed. The only way to keep a program alive is to have a second Watchdog application that is constantly pooling that process to ensure it's running.
So, you have two Applications; AppA (Main) and AppB (Watchdog).
AppA checks if AppB is running. If
not, AppA starts AppB.
AppB checks if AppA is running. If
not, AppB starts AppA.
But this is usually a design for a malicious process, so I hope you're not doing anything untoward.
You can see the following events in the message queue when End process is clicked:
WM_CLOSE // UI app
CTRL_CLOSE_EVENT //
Console app
But if your application does not close in a timely manner, then the kill command will be sent, which cannot be captured.
I'm pretty sure it is not possible, otherwise a single application could stop windows from ever shutting down. Even when the process is hung, killing it in task manager eventually works. If it was possible, malicous software, etc would probably have a hey-day using it - not only could they take control of various parts of your PC, they'd make sure you could never get it back again.

Resources