[launchd-dev] Loading WatchPath job: Launches if path changed within prior 0.5 secs

Jerry Krinock jerry at ieee.org
Sun Oct 30 14:19:56 PDT 2011


STEPS TO REPRODUCE:

• Install a launchd plist file, with a single WatchPaths parameter, but do not load it.
• Touch the watched path
• Load the job

EXPECTED RESULT:

Nothing should happen, because the file was touched *before* the job was loaded.

ACTUAL RESULT:

The job launches its program.

* * *

If I insert a slight wait between touching and loading, the job does not launch.  In the script which follows, the threshold wait is about 0.5 seconds.  In an application I've written, which invokes launchctl via NSTask, the threshold wait is 1-2 seconds.

This seems to be a bug in launchd (Mac OS X 10.7.2)?

You can demo it by running the following shell script.  The script attempts to experiment with different wait (sleep) values, but unexpectedly, only the first run of the function doTest ever "launches".

• If the first sleep value is about 0.4 or less, I get one "launch".
• If it's 0.5, I may or may not get one "launch".
• If it's 0.6 or more, I get zero "launches".
• Playing with the other sleep values in the script does not affect the results.
• Probably, the first time you run the script, there is no "launch".  Retry.

As you can see, there's a lot which does not make sense here.  Any explanations of this behavior would be appreciated.

Thanks,

Jerry Krinock


#!/bin/bash

OUR_AGENT_LABEL=TestLoadUnload
OUR_TOUCH_FILE=TestTouch.txt


function isAgentLoaded {
let IS_LOADED=`launchctl list | grep -c $OUR_AGENT_LABEL`
echo "Our agent loaded = $IS_LOADED"
}


function doTest {
isAgentLoaded

# Touch watched file
touch ~/Desktop/$OUR_TOUCH_FILE.txt
echo "Did touch"

sleep $SLEEPY_TIME
echo "Slept for $SLEEPY_TIME"

# Load Agent
launchctl load $OUR_AGENT_LABEL.plist
echo "Did load"

sleep 1
isAgentLoaded
sleep 1

# Unload Agent
launchctl unload $OUR_AGENT_LABEL.plist
echo "Did unload"

# Wait
sleep 1
}


# Create a small text file which launchd will watch
cd ~/Desktop
echo "This is a test" > $OUR_TOUCH_FILE


cd ~/Library/LaunchAgents

# Install a launchd plist file which will define our Agent
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $OUR_AGENT_LABEL.plist
echo "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\"" >> $OUR_AGENT_LABEL.plist 
echo "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" >> $OUR_AGENT_LABEL.plist
echo "<plist version=\"1.0\">" >> $OUR_AGENT_LABEL.plist
echo "<dict>" >> $OUR_AGENT_LABEL.plist
echo "	<key>Label</key>" >> $OUR_AGENT_LABEL.plist
echo "	<string>$OUR_AGENT_LABEL</string>" >> $OUR_AGENT_LABEL.plist
echo "	<key>ProgramArguments</key>" >> $OUR_AGENT_LABEL.plist
echo "	<array>" >> $OUR_AGENT_LABEL.plist
echo "		<string>osascript</string>" >> $OUR_AGENT_LABEL.plist
echo "		<string>-e</string>" >> $OUR_AGENT_LABEL.plist
echo "		<string>say \"Launched!\"</string>" >> $OUR_AGENT_LABEL.plist
echo "	</array>" >> $OUR_AGENT_LABEL.plist
echo "	<key>ThrottleInterval</key>" >> $OUR_AGENT_LABEL.plist
echo "	<integer>1</integer>" >> $OUR_AGENT_LABEL.plist
echo "	<key>WatchPaths</key>" >> $OUR_AGENT_LABEL.plist
echo "	<array>" >> $OUR_AGENT_LABEL.plist
echo "		<string>$HOME/Desktop/$OUR_TOUCH_FILE</string>" >> $OUR_AGENT_LABEL.plist
echo "	</array>" >> $OUR_AGENT_LABEL.plist
echo "</dict>" >> $OUR_AGENT_LABEL.plist
echo "</plist>" >> $OUR_AGENT_LABEL.plist

# Begin actual testing

SLEEPY_TIME=0.1
doTest

SLEEPY_TIME=0.2
doTest

SLEEPY_TIME=0.3
doTest

SLEEPY_TIME=0.4
doTest

SLEEPY_TIME=0.5
doTest

SLEEPY_TIME=0.6
doTest




More information about the launchd-dev mailing list