Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Repeat Loop times out and I don't want it to

Maybe there is a better way to do this but I want an action to take place whenever the modification date of a certain file changes. This is what I use but it errors because of a timeout after about 10 mins if the mod date doesn't change. I need this to be checking all the time.

on idle
tell application "Finder"
set UpdatedOLD to modification date of file aFile
set UpdatedNEW to modification date of file aFile
end tell

repeat while UpdatedOLD = UpdatedNEW
tell application "Finder"
set UpdatedNEW to modification date of file aFile
end tell
end repeat
end idle

How can I get this to work?

Posted on Jan 27, 2010 3:26 PM

Reply
Question marked as Best reply

Posted on Jan 27, 2010 3:58 PM

The idle handler is run after the run handler completes, repeating after the returned time interval (I am guessing that you are saving the script as run-only). Your example is timing out in the repeat statement because you aren't doing anything to terminate it (UpdateOLD will always equal UpdateNEW(. A better approach would be something like:

<pre style="
font-family: Monaco, 'Courier New', Courier, monospace;
font-size: 10px;
font-weight: normal;
margin: 0px;
padding: 5px;
border: 1px solid #000000;
width: 720px;
color: #000000;
background-color: #DAFFB6;
overflow: auto;"
title="this text can be pasted into the Script Editor">
tell application "Finder" to set UpdatedOLD to modification date of file aFile -- get the original date

on idle -- check
tell application "Finder" to set UpdatedNEW to modification date of file aFile

if UpdatedOLD is not equal to UpdatedNEW then -- the date changed
-- do stuff whenever the modification date is changed
tell application "Finder" to set UpdatedOLD to modification date of file aFile -- update
end if
return 30 -- check again in 30 seconds
end idle
</pre>
9 replies
Question marked as Best reply

Jan 27, 2010 3:58 PM in response to BenChase

The idle handler is run after the run handler completes, repeating after the returned time interval (I am guessing that you are saving the script as run-only). Your example is timing out in the repeat statement because you aren't doing anything to terminate it (UpdateOLD will always equal UpdateNEW(. A better approach would be something like:

<pre style="
font-family: Monaco, 'Courier New', Courier, monospace;
font-size: 10px;
font-weight: normal;
margin: 0px;
padding: 5px;
border: 1px solid #000000;
width: 720px;
color: #000000;
background-color: #DAFFB6;
overflow: auto;"
title="this text can be pasted into the Script Editor">
tell application "Finder" to set UpdatedOLD to modification date of file aFile -- get the original date

on idle -- check
tell application "Finder" to set UpdatedNEW to modification date of file aFile

if UpdatedOLD is not equal to UpdatedNEW then -- the date changed
-- do stuff whenever the modification date is changed
tell application "Finder" to set UpdatedOLD to modification date of file aFile -- update
end if
return 30 -- check again in 30 seconds
end idle
</pre>

Jan 27, 2010 6:19 PM in response to BenChase

Hello

I think you have stepped on a land mine set by OSX 10.6.
There's a fatal bug in Apple Event Manager in 10.6 such that one event in every 65535 events will be lost and never be replied, which will result in Apple Event timeout error on sender. This bug has been reported shortly after the 10.6 release and has not yet been fixed as of 10.6.2.

In your current script, you're continuously sending event to Finder and sooner on later send an event with the specific event id that is doomed to be lost. Judging from the time till you see the time out error, that is 10 min, you're at most sending 65535 / 600 = 109.225 events / sec to Finder. You can reduce the number of events by inserting some delay, e.g. 'delay 1' in your repeat loop but it can only defer the failure.

cf.
Re: Timed Out (Silence)
http://lists.apple.com/archives/applescript-users/2009/Oct/msg00117.html

Re: spurious timeout on nth Apple event on Snow Leopard
http://lists.apple.com/archives/applescript-users/2009/Nov/msg00041.html

---
A better way to achieve your task would be to let a launchd agent watch the file.
A recipe is as follows.

1) Save a compiled script in :

~/Library/Scripts/launchd/watchdog.1.scpt

with contents :

--SCRIPT
-- Here put your script that is to be triggered when the file is modified.
-- e.g.
tell application "System Events"
display dialog "The file is modified." giving up after 10
end tell
--END OF SCRIPT


2) Save a UTF-8 plain text file in :

~/Library/LaunchAgents/watchdog.1.plist

with contents :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>watchdog.1</string>
<key>Disabled</key>
<false/>
<key>Program</key>
<string>/usr/bin/osascript</string>
<key>ProgramArguments</key>
<array>
<string>osascript</string>
<string>/Users/USER_NAME/Library/Scripts/launchd/watchdog.1.scpt</string>
</array>
<key>WatchPaths</key>
<array>
<string>POSIX_PATH_TO_THE_FIILE</string>
</array>
</dict>
</plist>

*Change USER_NAME to your user name and POSIX_PATH_TO_THE_FIILE to the POSIX path to the file to be watched.



3) Issue the following command in Terminal to load the launchd agent :

launchctl load ~/Library/LaunchAgents/watchdog.1.plist

Or

3a) Log-out and re-log-in to load the launchd agent.

*The name 'watchdog.1.plist' and 'watchdog.1.scpt' and the script's location '~/Library/Scripts/launchd/' are mere examples. You may change them as you see fit.



cf.
http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/m an5/launchd.plist.5.html
http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/m an1/launchctl.1.html

Good luck,
H

Message was edited by: Hiroto (fixed typo)

Jan 27, 2010 7:31 PM in response to red_menace

Hello

I'm not sure but I'd think the AEM's event id is assigned globally, not per application or even per login session (under 10.6), and only reset by reboot.

So those who restart the machine often enough won't see this bug while those who use scripts sending events intensively will step on it soon, I suspect.

Well, they need to fix this asap, I'm sure!

Hiroto

Jan 28, 2010 7:30 AM in response to red_menace

Thanks for the advice. If this is a problem with just 10.6 wouldn't one solution be to have it run on 10.5? I am doing all the testing on my computer with 10.6 but eventually I am going to be moving it to another computer that is currently running 10.5. I was thinking about upgrading but maybe now I'll wait, as long as 10.5 doesn't also have the problem.

Jan 28, 2010 8:17 AM in response to BenChase

It would really depend on what you wind up doing. The Launchd method wouldn't have the problem, and using the *idle handler* in a stay-open application that checks every 10-15 seconds wouldn't have the problem either if you restart daily (or even once a week/month or so).

Using either of the above methods would also be better than the script constantly running in a repeat loop, since the script would only run periodically instead of constantly.

I'm not sure if the script you originally posted was complete, but there will be variable scoping issues if that is the case. An example of a complete working (save as a stay-open application) is:
<pre style="
font-family: Monaco, 'Courier New', Courier, monospace;
font-size: 10px;
font-weight: normal;
margin: 0px;
padding: 5px;
border: 1px solid #000000;
width: 720px; height: 340px;
color: #000000;
background-color: #DAFFB6;
overflow: auto;"
title="this text can be pasted into the Script Editor">
-- watch a file's modification date

property someFile : missing value -- the file to watch
property interval : 15 -- time duration between checks
global previousDate -- the previous modification date


on run -- set things up
if someFile is missing value then set someFile to (choose file) as text
tell application "Finder" to set previousDate to modification date of file someFile -- get the original date
end run


on reopen -- application double-clicked while runnning
-- in this case, just move focus to the application - can also do something like:

-- set someFile to (choose file) as text -- reset the watched file
-- tell application "Finder" to set previousDate to modification date of file someFile -- get the original date

end reopen


on idle -- check
tell application "Finder" to set currentDate to modification date of file someFile
if currentDate is not equal to previousDate then -- the date changed
doSomething()
tell application "Finder" to set previousDate to modification date of file someFile -- update
end if
return interval -- check again later
end idle


to doSomething() -- do stuff whenever the modification date is changed
tell application "System Events" to set frontApp to (name of processes whose frontmost is true) as text

activate me
beep
display alert "File changed" message "the modification date of file " & quoted form of someFile & " has changed." giving up after 5 -- the 'giving up after' time can be a bit fussy

tell application frontApp to activate
end doSomething
</pre>

Jan 28, 2010 10:43 AM in response to red_menace

Thanks for the replies. My script works it just times out when its in the repeat loop if nothing happens. I only showed you part of the script maybe a better explanation would help.

The file is on a sever volume and is occasionally modified by other people. While in the repeat loop it is constantly checking for the mod date to be different then it was at the beginning of the "on idle". Once the file is modified the mod date changes and the repeat loop is exited and the rest of the process is completed. After the process is completed it "idles" back to the beginning and back into the repeat loop waiting for the file to be changed again.

All of this work beautifully and is extremely simple except, like I pointed out, after about 10 minutes the script errors because of a timeout in the repeat loop. The file being checked is randomly modified from maybe a couple times a day to possibly every couple days. But as soon as its changed I need the rest of the process to be run as immediately as possible. Adding a delay, like previously mentioned, will just delay the inevitable if no modification is made within that time frame. And at a certain point adding too much of a delay would defeat the purpose anyway.

Jan 28, 2010 12:04 PM in response to BenChase

The idle handler is normally called every 30 seconds (the default time can be changed), so using it as intended won't send quite the number of events that a repeat loop will. I'm not sure what the default response time using Launchd would be, but if you are needing a script to sit in a loop constantly getting the modification time, for now I think you are limited to using Launchd or Leopard. Hopefully this gets fixed in the next *Snow Leopard* update.

Repeat Loop times out and I don't want it to

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.