Friday, November 24, 2017
  • Index
  •  » Code Exchange
  •  » Automated force-quitting of a runaway Applescript application

#1 2015-05-21 09:50:46 am

bmose
Member
From:: Massachusetts
Registered: 2006-01-03
Posts: 219

Automated force-quitting of a runaway Applescript application

On occasion, one needs to force-quit a runaway Applescript application, for example, an application caught in an endless loop, or a stay-open application that did not properly quit itself. The following do shell script command, which should be placed at the start of an Applescript application's execution code, creates a shell script that runs in the background and performs two tasks:
    (1) force-quits the Applescript application in which it is embedded if the application is still running after forceQuitTime seconds
    (2) quits itself if it finds that the Applescript application is no longer running upon repeated testing of the application's run status every queryCycleTime seconds

The user provides two variable values for the do shell script command:
    forceQuitTime
        - the number of seconds the background shell script should wait before force-quitting the Applescript application
    queryCycleTime
        - the number of seconds the background shell script should wait between repeated checks of the Applescript application's run status to determine if the application is no longer running and thus to signal the shell script to quit itself

Applescript:


set {forceQuitTime, queryCycleTime} to {3600, 60} -- the user sets these two values
do shell script "(" & ¬
   "processName=$(defaults read " & ((path to me as text) & "Contents:Info.plist")'s POSIX path's quoted form & " CFBundleExecutable)" & linefeed & ¬
   "pid=$(pgrep -nx \"$processName\")" & linefeed & ¬
   "launchTime=$(ps -p $pid -o start=)" & linefeed & ¬
   "while [[ SECONDS -lt " & forceQuitTime & " ]]; do" & linefeed & ¬
   "    [[ \"$launchTime\" = $(ps -p $pid -o start=) ]] && : || exit 0" & linefeed & ¬
   "    timeRemaining=$(( " & forceQuitTime & " - SECONDS ))" & linefeed & ¬
   "    [[ timeRemaining -lt " & queryCycleTime & " ]] && sleep $timeRemaining || sleep " & queryCycleTime & linefeed & ¬
   "done" & linefeed & ¬
   "[[ \"$launchTime\" = $(ps -p $pid -o start=) ]] && kill -9 $pid || :" & ¬
   ") &>/dev/null &" -- this statement is placed without modification at the start of the application's execution code

-- The user may supply any desired number of seconds for forceQuitTime and queryCycleTime. In the current assignment statement, 3600 signifies that the shell script will force-quit the Applescript application if still running after 1 hour (3600 seconds), and 60 signifies that the shell script will test the application's run status every minute (60 seconds) and quit itself if it finds that the application is no longer running

Explanatory notes:
    initial "(" and final ") &>/dev/null &"
        - Runs the shell script in the background and executes the script's commands as a subprocess
        - Both features are necessary for pgrep to be able to recognize the current process
    "processName=$(defaults ..."
        - Gets the Applescript application's process name from the Info.plist file's CFBundleExecutable property
    "pid=$(pgrep ..."
        - Gets the Applescript application's Unix process ID number by providing pgrep with the process name
        - The pgrep command's -n option restricts matching only to the newest process with the Applescript application's process name
          and prevents pgrep from matching an older application with an identical process name
        - The "do shell script" command should be placed at the start of the application's execution code to make vanishingly
          small the chance of pgrep matching an identically named process even newer than the current application
    "launchTime=$(ps -p ..."
        - Gets the clock time the Applescript application was launched, e.g., "10:17AM"
        - This value acts an additional means besides the Unix process ID number of correctly identifying the current application and
          serves as a safeguard against the shell script force-quitting another application with the same Unix process ID number
          as might otherwise occur if, for instance, the user specified a very long value for forceQuitTime (days to weeks)
    "while [[ SECONDS -lt ..."
        - Sets up a while loop that repeatedly checks if the application is still running
        - Uses the special variable SECONDS, which contains the shell script's execution time in seconds
    "    [[ \"$launchTime\" = ..."
        - Tests if the Applescript application is still running; if not, causes the background shell script to quit itself ("exit 0")
        - Uses two criteria to correctly identify the Applescript application: Unix process ID number ("-p "$pid") and
          launch time ("\"$launchTime\" = " ... "-o start=")
    "    timeRemaining=$(( ..." and "    [[ timeRemaining ..."
        - Pauses the background shell script for queryCycleTime seconds before the next while loop execution
        - If the time remaining before force-quitting is less than queryCycleTime, uses the former value for the pause time rather
          than queryCycleTime
    "[[ \"$launchTime\" = ..."
        - Tests if the Applescript application is still running after forecQuitTime seconds and, if so, force-quits it ("kill -9 $pid")


Edit note: A typo was corrected on line 7 of the shell script.

Last edited by bmose (2015-05-21 12:33:54 pm)

Offline

 
  • Index
  •  » Code Exchange
  •  » Automated force-quitting of a runaway Applescript application

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)