Taming Launchd

December 30th, 2006

Developers, and some power users who are reading this have probably heard of launchd. It’s Apple’s “mama process,” responsible for launching other processes at startup, login, at regular intervals, or on demand. If you open the Activity Monitor application, and view “All Processes, Hierarchically,” you’ll see that there are only two top-level processes: kernel_task, and launchd. The kernel sits there and does its thing, while launchd spawns all the other processes that make up your Macintosh computing experience.

One big benefit of launchd to end-users is that most of what gets launched can be easily examined by perusing the configuration files. Launchd looks in five well-defined locations for launchable items:

/System/Library/LaunchDaemons
/System/Library/LaunchAgents
/Library/LaunchDaemons
/Library/LaunchAgents
~/Library/LaunchAgents

So all you have to do to get a feel for (most of) what launchd is up to is start poking around in those directories. For each independent “launch” that launchd controls, you’ll find a corresponding configuration property list file. For instance, you’re guaranteed to find a bunch of examples in /System/Library/LaunchDaemons, and depending on which third-party packages you’ve installed, you might find things in other places, as well.

Launchd In Context: FTP

Take a quick look at ftp.plist, one of the system launch daemons. Depending on how you’ve configured your system, you’ll either see that a “Disabled” key is present and set to “true,” or it is absent. This corresponds directly to the “FTP Access” item in the System Preference’s “Sharing” panel. Go ahead and toggle the setting in your preferences, and observe that the ftp.plist file is immediately updated to reflect the new setting. This tells launchd that it should no longer consider launching the ftp daemon when an incoming ftp connection is attempted.

What constitutes an incoming ftp connection? Look further down the ftp.plist and you’ll find an entry with key name “SockServiceName” and a value of “ftp”. Launchd uses this name to lookup the socket port/protocol information for the named service from /etc/services. In this case, when an incoming connection is attempted on port 21, launchd will, if this item is not disabled, launch the daemon at /usr/libexec/ftpd, in order to handle the incoming connection. Groovy, huh? Read more about network handlers and other on-demand daemons.

Boot-Time King

I said above that these configuration files reveal “most of” what launchd is up to with regard to running things on your system. Because launchd can’t handle all types of configurations, and because its introduction has been sort of gently staged, it’s responsible for running a lot of the older mechanisms like /etc/rc, StartupItems, etc. This means that launchd is basically responsible for everything from when the kernel gets loaded on. That includes booting your Mac!

Things have been in such flux over the past few years that it’s hard to keep a straight answer when it comes to exactly what takes place at boot time. Excellent overviews such as Mac OS X System Startup by Amit Singh, or The Boot Process by Apple, are liable to become outdated as launchd continues to evolve.

Fortunately, the entire process is transparently observable, because launchd is open source. If you’re ever in doubt about any nuance of the startup process, just look at the source code. The repository even contains the boot-time configuration file “/etc/rc”, and the source for antiques like SystemStarter. You can even check out how the boot process is going to look in Leopard. (Note: free registration on macosforge.com required). I couldn’t figure out how to check out those repository URLs from the command-line, but I discovered an alternate URL that works, and doesn’t seem to require registration.

Editing Launchd Configuration Files

It won’t take you long to discover that the launchd configuration files, while elegant and modular, are a bit of a pain to read, let alone edit. Fortunately, a couple of third-party solutions exist to ease this task.

Lingon, by Peter Borg, is a very powerful editor which also serves as a sort of browser for all the existing configuration files on your Mac. You can selectively start or stop any existing configuration, and it takes care of asking you to authenticate for editing those system-owned files (after warning you profusely not to do so!). It even sports a “wizard” interface that asks in relatively plain English what it is you’re trying to accomplish, and guides you through the creation of new, custom launchd configurations.

While Lingon is essentially easy to use, it has some rough edges which scream for refinement. I’d really like to see the application receive a UI overhaul. Lots of little awkward UI elements and poorly phrased dialog make it slightly less than a 100% success. But it sure beats editing in vi, or even Property List Editor.

One of Lingon’s nicest features is its “Expert” pane, which allows you to examine and edit the raw XML of a configuration at any time. This is so useful that I’d like to see if featured as a full-time view, perhaps in a hideable split view pane. It would be fun to be able to watch the changes live in the XML source while tweaking details in the UI. But Lingon is, in the spirit of launchd itself, open source. So any shortcomings that ultimately get me down can be remedied to my own (or your own) liking.

Apparently I wasn’t the only person to object slightly to the UI of Lingon. Launchd Editor is a $5, closed-source alternative that bites off a much smaller feature set, while trying to improve on the UI of Lingon. It’s clear by observing some of the configuration panes that Launchd Editor was inspired by Lingon (or vice-versa, I’m not positive which came first, but I’d guess Lingon did). Some of the control layout is almost identical to Lingon, but touched up a bit in alignment and wording, mostly for the better.

Launchd Editor is limited by its adoption of a document-centric model, such that the user has to specifically locate and open a configuration file. It also lacks the start/stop/load features of Lingon. Overall I’d say it’s worth using Lingon in spite of its rough UI, but minimalists might prefer Launchd Editor.

Launchd For Developers

So far I’ve talked about how the system uses launchd for its services, and sort of alluded to the fact that you might come up with your own configurations to suit your personal needs. But developers should also take heed of launchd as a mechanism for automating tasks on behalf of users. One example of this is Noodlesoft’s Hazel, which uses launchd configuration rules to periodically check the status of “watched folders” and perform housekeeping tasks on them. By saving configurations to the user’s LaunchAgents folder, and then loading them with the launchctl command-line tool, it pushes off timing responsibility to launchd. Nifty!

Summary

Launchd is a super addition to Mac OS X, and a stellar example of Apple’s commitment to improving Unix for both end-user and architectural benefit. Hopefully if you hadn’t gotten a chance to take a close look at it before, you’ll be encouraged to do so after reading this article.

5 Responses to “Taming Launchd”

  1. Mark Dalrymple Says:

    Beware, launchd is pretty broken in Tiger, especially for per-user agents. Sometimes they’ll start in the wrong context (like if you ssh into a machine – see tn2083), sometimes they won’t shut down properly, and keep running (and re-launching) after you log out. Plus there are race conditions if you’re using watchPaths or queueDirectories. If you stay running, you won’t get any additional notifications, even if you use ServiceIPC, so you end up using kqueue() to watch the things that launchd is watching, Just In Case. Also some of the launchd API is wishful thinking, and isn’t actually implemented. (see Launchd and domain sockets)

    Also watch out for launchd editor if you use unix domain sockets, it’ll corrupt your plist file. My bug report is still sitting there. I’ve since abandoned launchd and launchd editor for what I was originally intending to use it.

  2. Tom Harrington Says:

    When considering launchd one should beware that per-user agents (those whose plists reside in one of the LaunchAgents folders) are in many cases much less useful than one might expect.

    If you set up a LaunchAgents entry, launchd will start the process when the user logs in. If it’s a persistent process– one which starts up and keeps running instead of one that starts up, does some work, and exits– then launchd will stop it (via SIGTERM) when they log out.

    That actually works OK, as far as described. However launchd doesn’t quite clean things up normally on log-out. The upshot is that if you log in, log out, and then back in, your LaunchAgents entries will not start up on the second login (or any subsequent logins).

    I had originally intended to use launchd with MondoMouse, but on discovering this limitation (confirmed by Apple engineers) I had to abandon the plan and go with a login item instead (and thanks to Uli for his sample code that made this easier). Paul Kim was able to use launchd with Hazel because Hazel’s launchd-started jobs are not persistent– they start up, do something useful, and then start

    Also for what it’s worth– unless I’m very much mistaken, Hazel’s launchd usage doesn’t involve any sort of polling-like behavior to check watched folders. I’m pretty sure launchd makes use of Mac OS X (BSD’s really) kqueue system to receive notifications of filesystem changes without the need for regular checking.

  3. Paul Kim Says:

    Thanks for the mention though the irony of using me as the poster boy for launchd is that I am currently considering ditching it. The problem? Well, one thing that is mentioned in the tech note that Mark posted above is that after logout, the user context is disabled. It wasn’t immediately obvious to me but after talking to Apple support, the user’s launchd and everything it launches runs in this context and when the user re-logs in. The side effect is that none of these processes are able to get rights to any mach ports. While Hazel does not create any ports directly, it ends up using Launch Services and other subsystems that need mach ports so it throws all sorts of errors in this situation.

    There’s a good chance I will have to write my own daemon and stop using launchd which is too bad since it’s works well for my needs. While there’s a chance it will be fixed in Leopard, I imagine a good percentage of my users will be on Tiger for some time. It’s unfortunate since the new daemon would be another moving part that I would have to write and maintain but them’s the breaks.

    Oh, and to Tom’s point about polling: Hazel does poll as well. Certain conditions are time based and so having rules run only when a change in the folder occurs is not sufficient. This is also why, among other reasons, Folder Actions (which Hazel gets compared to now and then) are not a suitable replacement for Hazel since if there’s no activity in the folder, time based rules will not get run.

  4. Adam Knight Says:

    For the record, Launchd Editor was first, and the idea was only to create the file correctly rather than be a complete solution. I’ve pondered doing the whole schebang at some point, however. Perhaps in ’07 I’ll make a second, more full version that does those things.

  5. Nathaniel Says:

    I’m pretty sure Launchd Editor came first. I remember using it for a while, and being really excited when Lingon came out.

Comments are closed.

Follow the Conversation

Stay up-to-date by subscribing to the Comments RSS Feed for this entry.