Question

I'm writing an application which will potentially be invoked by more than one launchd job – that is, there might be two distinct LaunchAgent .plist files which invoke the application with different program arguments or in different conditions. I'd like the application to be able to examine the job, or the job's .plist, so it can adjust its behaviour based on what it finds there.

In particular, supposing a program foo could be started up from both A.plist and B.plist, I'd like the program to be able to preserve different state depending on which job/plist invoked it. If all I can do is detect the (presumed distinct) Label of the job, that will be enough (though more would be better).

The obvious ways to do this are using different flags in the ProgramArguments array in the job, or to set different values in EnvironmentVariables, but both of those feel fragile, both imply duplication of bits of configuration, and both require extra documentation (“copy the value of the Label into EnvironmentVariables field FOO...; don't ask why”).

I can see the function SMJobCopyDictionary. With that, it appears that I can get access to the job's dictionary – ie, this information is available in principle – but I need to know the job's label first. Function SMCopyAllJobDictionaries allows me to iterate through all of the jobs, but it's not obvious how I'd find the one which invoked a particular instance of the application.

Googling launchd read job label or launchd self dict (or similar) don't come up with anything useful.

Was it helpful?

Solution

Take a look at the SampleD code on Apple's site. This code shows how daemon's can access calling launchd information.

Looking at the launch.h header, I suspect LAUNCH_JOBKEY_LABEL is what you are after.

OTHER TIPS

Using the ProgramArguments is, in fact, probably the best way to handle this. It will make your code more portable (e.g. making it possible to launch in Linux, for example, or under a different launch daemon) to use program arguments that configure the behavior rather than relying on the program invocation chain.

With regard to program arguments, though, I would suggest not copying the label, but rather using the specific flags that differ between the jobs. For example, you might set --checkpoint-file and --log-file in both A.plist and B.plist to files that happen to include "A" or "B" in their names. Doing this will make the application code that depends on --checkpoint-file and --log-file much clearer, though, than if it were to make arbitrary choices based on some label and will also allow you to run the command directly from the commandline and have it still work despite there not being an invoking PLIST file.

Summary: I think the answer here is a qualified no.

Graham Miln's answer (which I've accepted) shows that this is possible in fact, but the interface he mentions is apparently documented nowhere other than in this sample code, and also possibly in Mac OS X Internals: A Systems Approach (Amit Singh, http://osxbook.com, thanks to Mitchell J Laurren-Ring for pointing this out).

I also asked about this on the launchd-dev list (see the thread starting with my question), and Damien Sorresso suggested that this interface was “really only so that jobs can check in with launchd to obtain listening sockets. They were way too general at the outset.”

Put together, I'm left with the feeling that, while the behaviour I want seems possible, and while I think it's neater in this case than passing more state in environment variables, the API to support such behaviour is, if not deprecated, than at least somewhat discouraged, and at any rate not idiomatic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top