1

I wish to load and run a Lisp program in CCL in the background automatically when my Mac (OS 10.9) boots. I have a launchd plist that I've saved to /Library/LaunchDaemons,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.icecreamcomputer</string>
    <key>ProgramArguments</key>
    <array>
            <string>sudo</string>
            <string>/Applications/ccl/./dx86cl</string>
            <string>-l</string>
            <string>/Users/frank/Documents/Lisp/ice-cream-computer/ice-cream-computer.lisp</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>

When I call

launchctl load /Library/LaunchDaemons/com.icecreamcomputer.plist

from the terminal, I can see in top that dx86cl runs for a few seconds, then goes away. Afterward launchd lists the job as having exited. However, if I call

sudo /Applications/ccl/./dx86cl -l /Users/frank/Documents/Lisp/ice-cream-computer/ice-cream-computer.lisp

from the terminal, my program starts up and stays running no problem. What could be causing my launchd job to quit immediately after starting?

Here are entries from /var/log/system.log:

Apr 15 10:01:55 frynseytv.icecreamcomputer.com sudo[34963]:     root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/Applications/ccl/./dx86cl -l /Users/frank/Documents/Lisp/ice-cream-computer/ice-cream-computer.lisp
Apr 15 10:01:58 frynseytv com.apple.launchd[1] (com.icecreamcomputer): Throttling respawn: Will start in 8 seconds
Apr 15 10:02:00 frynseytv com.apple.launchd.peruser.501[306] (com.icecreamcomputer[34965]): open("/var/log/icecreamcomputer.log", ...): 13: Permission denied
Apr 15 10:02:02 frynseytv com.apple.launchd.peruser.501[306] (com.icecreamcomputer): Throttling respawn: Will start in 8 seconds

Apparently it didn't have permission to open a log called "/var/log/icecreamcomputer.log," and indeed no such file or directory exists. Although that seems odd because root/wheel owns /var/log/icecreamcomputer.log, and root runs launchd and the other processes launchd launches, doesn't it? Here's an excerpt from /var/log/icecreamcomputer.log. It shows what normally prints to stdout when icecreamcomputer.lisp loads. What it lacks is logged http server activity, like receiving and fulfilling requests.

Welcome to Clozure Common Lisp Version 1.9-r15759  (DarwinX8664)!
? 
==== quicklisp quickstart loaded ====

To continue with installation, evaluate: (quicklisp-quickstart:install)

For installation options, evaluate: (quicklisp-quickstart:help)

To load "hunchentoot":
Load 1 ASDF system:
hunchentoot
; Loading "hunchentoot"

Actually when I tail -f /var/log/icecreamcomputer.log, it continues its cycles of throttling respawns and saying that it fails to write to its log even after I call launchctl unload /Library/LaunchDaemons/com.icecreamcomputer.plist. It only stopped cycling upon server reboot. What gives?

After the restart, I attempted to load the daemon again. No error messages, but launchctl list shows the process has exited, and tailing icecreamcomputer.log showed no activity while I loaded the daemon's plist.

fpt
  • 121
  • 4

1 Answers1

1

It sounds like your LISP programming is violating launchd's daemon requirements:

"You must not daemonize your process. This includes calling the daemon function, calling fork followed by exec, or calling fork followed by exit. If you do, launchd thinks your process has died. Depending on your property list key settings, launchd will either keep trying to relaunch your process until it gives up (with a “respawning too fast” error message) or will be unable to restart it if it really does die.”

Source: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html

To understand launchd better — particularly for the plist syntax — I recommend writing a hello world script with an infinity loop using the logger(1) command to write to sylog ever ~5 seconds. Make the script work in the foreground and the background to see the difference. Also, use plutil(1) to double check for easily overlooked syntax errors.

Apple’s launchd jobs in /System/Library/LaunchDaemons are also an excellent reference. Note that apache one in particular, which uses:

/usr/sbin/httpd -D string>FOREGROUND

To solve launchd's daemon requirement.

Good luck!

  • Thanks! It could be that one of the library packages my program loads does such a thing. The simpler hello world program I'd already tried worked fine. Ultimately I got what I wanted by moving the program to a Raspbian Linux machine and launching it with an init script. Your suggestion and my experience with the two systems implies that launchd, and Mac OS X, is ill-suited to launching things like webservers at startup. – fpt Apr 22 '14 at 14:24