Index

catch condition {commands} {remedial_commands}

Abort the specified block of commands if a given condition becomes true.

Arguments:
Boolean condition
The condition who's truth value aborts the block of commands.
commands
A block of commands to execute. The commands will be executed to completion unless the condition becomes true.
remedial_commands
An optional block of commands to execute if the condition becomes true.

Example 1:
In the following example, if the source sets while the enclosed statements are being executed, or the statements take more than 10 minutes to complete, execution of these statements is aborted, and execution resumes with the print statement that follows the catch statement.
  catch $signaled(source_set) | $elapsed > 0:10:0 {
    track jupiter
    until $acquired(source)
    until $elapsed > 0:0:30
    track saturn
    until $acquired(source)
    until $elapsed > 0:10:0
  }
  print "Finished"
Example 2:
This example is similar to the previous one, except that here an extra block of remedial commands has been provided. This block of commands is only executed if the catch condition becomes true. In this case it tells the user that the statements had to be aborted, and why. After it has finished executing, execution continues with the print statement that follows the catch statement.
  catch $signaled(source_set) | $elapsed > 0:10:0 {
    track jupiter
    until $acquired(source)
    until $elapsed > 0:0:30
    track saturn
    until $acquired(source)
    until $elapsed > 0:10:0
  } {
    if($signaled(source_set)) {
      print "The source set"
    } else {
      print "Observations took too long"
    }
    exit
  }
  print "Finished"
Context:
Catch commands provide a way to abort a block of commands when specified events occur. This is important when using until statements, because these can block script execution indefinitely, and unless every one of these until commands checks all conceivable conditions, it is possible that script execution will be held up much longer than intended. For example, in the following example, if Jupiter or Saturn were to set before the telescope reached them, then the script would pause until they rose again.
  track jupiter
  until $acquired(source)
  until $elapsed > 0:0:30
  track saturn
  until $acquired(source)
  until $elapsed > 0:0:30
One could deal with this by adding a " | $signaled(source_set)" clause to each of the until statements, but this becomes troublesome if there are a lot of such statements, and could be impossible if the code is being imported from somebody else's file. Both of these problems are resolved by enclosing the block of statements in a catch block, and writing the stopping condition just once.
  catch $signaled(source_set) {
    until $acquired(source)
    until $elapsed > 0:30:0
    track saturn
    until $acquired(source)
    until $elapsed > 0:30:0
  }
Note that the catch condition is only evaluated at certain times. It is evaluated just before the first of its enclosed statements is about to be run, whenever a script signal arrives, and repeatedly while until statements are running. If the condition is found to be true at any of these points, then the enclosed block of statements is aborted. Specifically, what happens is as follows:

  1. First, if the statements that the catch statement aborts, include any user-defined commands, and those commands previously used the at_end command to register termination cleanup statements, then those statements are executed, starting from those of the innermost nested command.
  2. Next, if the catch statement specifies a block of remedial commands, then these are executed.
  3. Finally, execution continues with the first statement that follows the catch command.

The clauses of nested catch statements are scanned in order from the innermost catch statement to the outermost catch statement. After each scan through these clauses, the outermost catch statement whose clause is found to be true, is the one that aborts its enclosed statements. So if two or more nested catch statements test the same condition, and that condition doesn't change while the clauses are being scanned, then it is the outermost of these catch statements that aborts the statements that it encloses. However if the triggering event is an aborted command, then it is the innermost of these catch statements that aborts its commands, because the aborted() function that tests for this event, only returns true for the first catch statement clause that invokes it, after an abort.


Martin Shepherd (18-May-2010)